Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Edited by NavBot (jp)

The C90 standard allows for implicit typing of variables and functions. Because implicit declarations lead to less stringent type checking, they can often introduce unexpected and erroneous behavior or even security vulnerabilities.

The C99 standard requires type identifiers and forbids implicit function declarations. After issuing the diagnostic, an implementation may choose to assume an implicit declaration and continue translation to support existing programs that used this feature.

Noncompliant Code Example (Implicit int)

C90 Section 6.5.2 allows for the absence of type specifiers in a declaration. In these cases, the type is defined to be that of a signed int.

Do not rely on implicit int typing. C99 Section 6.7.2, "Type specifiers" states:

At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name.

This noncompliant code example omits the type specifier.

Code Block
bgColor#FFCCCC
extern foo;

Most C90 implementations do not issue a diagnostic for the violation of this C99 constraint. Many C99 translators will continue to treat such declarations as implying the type int.

Compliant Solution

This compliant solution explicitly includes a type specifier.

Code Block
bgColor#ccccff
extern int foo;

Noncompliant Code Example (Implicit Function Declaration)

Implicit declaration of functions is not allowed: every function must be explicitly declared before it can be called. In C89, if a function is called without an explicit prototype, the compiler provides an implicit declaration.

The C90 Standard includes the requirement:

If the expression that precedes the parenthesized argument list in a function call consists solely of an identifier, and if no declaration is visible for this identifier, the identifier is implicitly declared exactly as if, in the innermost block containing the function call, the declaration extern int identifier(); appeared.

A C99 implementation will not perform implicit function declarations.

If a function declaration is not visible at the point at which a call to the function is made, some compilers assume an implicit declaration of

extern int func();

However, to conform with C99, you must explicitly prototype every function before invoking it. This noncompliant example fails to prototype the foo() function before invoking it in main().

Code Block
bgColor#FFCCCC
int main(void) {
  int c = foo();
  printf("%d\n", c);
  return 0;
}

int foo(int a) {
  return a;
}

Because the compiler assumes foo() to have type extern int foo(), it cannot diagnose the missing argument.

Compliant Solution (Implicit Function Declaration)

In this compliant solution, a prototype for foo() appears before the function invocation.

Code Block
bgColor#ccccff
int foo(int);

int main(void) {
  int c = foo(0);
  printf("%d\n", c);
  return 0;
}

int foo(int a) {
  return a;
}

For more information on function declarations see DCL07-C. Include the appropriate type information in function declarators.

Noncompliant Code Example (Implicit Return Type)

Similarly, do not declare a function with implicit return type. If it returns a meaningful integer value, declare it int. If it returns no meaningful value, declare it void.

Code Block
bgColor#ffcccc
foo(void) {
  return UINT_MAX;
}

int main(void) {
  long long c = foo();
  printf("%lld\n", c);
  return 0;
}

Because the compiler assumes that foo() returns a value of type int, UINT_MAX is incorrectly converted to -1.

Compliant Solution (Implicit Return Type)

This compliant solution explicily defines the return type of foo() as unsigned int.

Code Block
bgColor#ccccff
unsigned int foo(void) {
  return UINT_MAX;
}

int main(void) {
  long long c = foo();
  printf("%lld\n", c);
  return 0;
}

Risk Assessment

Occurrences of an omitted type specifier in existing code are rare, and the consequences are generally minor, perhaps resulting in abnormal program termination.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DCL31-C

low

unlikely

low

P3

L3

Automated Detection

GCC Compiler Version 4.4.0 can detect violations of this rule when the -Wimplicit and -Wreturn-type flags are used.

Compass/ROSE can detect violations of this rule.

Klocwork Version 8.0.4.16 can detect violations of this rule with the IF_MISS_DECL and RETVOID.IMPLICIT checkers.

Related Vulnerabilities

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

References

Wiki Markup
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.7.2, "Type specifiers", Section  6.5.2.2, "Function calls"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "OTR Subprogram Signature Mismatch"
\[[Jones 08|AA. C References#Jones 08]\]
\[[MISRA 04|AA. C References#MISRA 04]\]


      02. Declarations and Initialization (DCL)      DCL32-C. Guarantee that mutually visible identifiers are unique