Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Functions that take accept no parameters arguments should explicitly declare a void parameter in their parameter list. This holds true in both the declaration and definition sections (which should match). Many compilers today still allow implicitly declared functions, even though C99 has eliminated them.

...

A similar rule deals with parameter type in a more general sense: DCL07-C. Include the appropriate type information in function declarators.

Noncompliant Code Example (Ambiguous Interface)

In this noncompliant code example, the caller calls foo() with an argument of 3. The caller expects foo() to accept a single int argument and to output the argument as part of a longer message. Because foo() is declared without the void parameter, the compiler will not perform any caller check. It is therefore possible that the caller may not detect the error. In this example, for instance, foo() might output the value 3 as expected.

...

Code Block
bgColor#FFCCCC
void foo() {
  int i = 3;
  printf("i value: %d\n", i);
}

...

/* caller */
foo(3);

Compliant Solution (Ambiguous Interface)

In this compliant solution, void is specified explicitly as a parameter.

Code Block
bgColor#ccccff
/* compile using gcc4.3.3 */
void foo (void) {
  int i = 3;
  printf("i value: %d\n", i);
}

Implementation Details (Ambiguous Interface)

When the above compliant solution is used and foo(3) is called, the GCC compiler will issue the following diagnostic, which alerts the programmer 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 this noncompliant code example, a user with high privileges feeds some secret input to the caller that the caller then passes to foo(). Because of the way foo() is defined, we might assume that there is no way for foo() to retrieve information from the caller. However, because the value of i is really passed into a stack (before the return address of the caller), a malicious programmer can change the internal implementation and copy the value manually into a less privileged file.

Code Block
bgColor#FFCCCC
/* compile using gcc4.3.3 */
void foo() {
  /* use asm code to retrieve i
   * implicitly from caller
   * and transfer it to a less privileged file */
}

...

/* caller */
foo(i); /* i is fed from user input */

Compliant Solution (Information Outflow)

Code Block
bgColor#ccccff
void foo(void) {
  int i = 3;
  printf("i value: %d\n", i);
}

Again, the simplest solution is to explicitly specify void as the only parameter.

Risk Assessment

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

DCL20-C

medium

probable

low

P12

L1

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Other Languages

In C++, foo() and foo(void) have exactly the same meaning and effect, so this rule doesn't apply to C++. However, foo(void) should be declared explicitly instead of foo() to distinguish it from foo(...), which accepts an arbitrary number and type of arguments.

References

Wiki Markup
\[[ISO/IEC 9899:1999|AA. References#ISO/IEC 9899-1999]\] Forward and Section 6.9.1, "Function definitions"
\[[C void usage|http://tigcc.ticalc.org/doc/keywords.html#void]\]