Functions that takes take no parameter parameters should explicitly declare a void parameter in their parameter list. This holds true during both the declaration and definition section sections (and they should match), . Many compilers today still allow implicitly declared functions, even though C99 has eliminated them.
Wiki Markup |
---|
Defining a function with a void argument list differs from declaring the functionit with no arguments, because in the latter case, the compiler will not check whether the function is called with parameters at all \[[C void usage|http://tigcc.ticalc.org/doc/keywords.html#void]\]. ThusConsequently, function calling with arbitrary parameters will be accepted without a warning at compile time. |
Failure to declare a void parameter will result in
- an ambiguous functional interface between the caller and callee
...
- sensitive information outflow
...
There is a A similar rule that deals with parameter type in a more general sense: DCL07-C. Include the appropriate type information in function declarators.
In C++ , the usage of foo()
and foo(void)
has exactly the same meaning and effect, so this rule doesn't apply to C++. But it is still recommended to explicitly declare foo(void)
instead of foo()
to distinguish from foo(...)
, which will then take arbitrary parameters.
Noncompliant Code Example (
...
Ambiguous Interface)
In this particular noncompliant code example, the caller gives a call to foo
with a parameter specified as 3. Because foo()
is declared without void
, the compiler will not perform any caller check. Due to the accidental internal implementation, the function foo()
outputs a value: 3 which matches with caller's temptation. In an inherited code base where foo and caller are developed at different times, this can lead to the caller's belief that foo()
actually accepts one integer as parameter and foo()
will output the corresponding message when the parameter is changed.
In fact, no parameter specified for a function has the same meaning as arbitrary paramemtersparameters, which means that the caller can may feed arbitrary number of parameters to the function.
Code Block | ||
---|---|---|
| ||
void foo() { int i = 3; printf("i value: %d\n", i); } ... /* caller */ foo(3); |
Compliant Solution (
...
Ambiguous Interface)
In this examplecompliant solution, void
is explicitly specified as a parameter.
Code Block | ||
---|---|---|
| ||
/* compile using gcc4.3.3 */ void foo (void) { int i = 3; printf("i value: %d\n", i); } |
Implementation Details (
...
Ambiguous Interface)
In gcc-4.3.3, when When the above compliant solution is used and foo(3)
is called, gcc the GCC compiler will issue the following diagnostic, which alerts the programmer of about the misuse of the function interface.
Code Block |
---|
error: too many arguments to function âfooâ |
Noncompliant Code Example (
...
Information Outflow)
Another possible vulnerability is the leak of privileged information. In the following this noncompliant code example, suppose a user with high privileges feeds some secret input into the caller that the caller , then caller will pass the info passes to foo()
. Because of the way function foo()
is defined, it is easy to assume that there is no way that foo()
can retrieve info from caller. However, because the value of i
is really passed into stack (before the return address of caller), a malicious programmer can change the internal implmentation implementation and copy the value manually and contain it in a less privileged file.
Code Block | ||
---|---|---|
| ||
/* compile using gcc4.3.3 */ void foo() { /* use asm code to retrieve i * implicitly from caller * and transfer it to a less privilege file */ } ... /* caller */ foo(i); /* i is fed from user input */ |
Compliant Solution (
...
Information Outflow)
Code Block | ||
---|---|---|
| ||
void foo(void) { int i = 3; printf("i value: %d\n", i); } |
...