You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

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

Two new features of C99 are to require type identifiers and to forbid implicit function declarations. The effect is to guarantee the production of a diagnostic that will catch an additional category of 25 programming errors. After issuing the diagnostic, an implementation may choose to assume an implicit declaration and continue translation to support existing programs that exploited this feature.

Non-Compliant Code Example (implicit int)

Don't 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.

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 declaration as implying the type int.

Compliant Solution

extern int foo;

Non-Compliant 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 included 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, for conformance to C99, you should explicitly prototype every function before making a call to it.

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

int foo(int a) {
  return a;
}

Since the compiler assumes foo() to have type extern int foo(), it cannot spot the missing argument and a bogus value is printed.

Compliant Solution (implicit function declaration)

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-A. Include the appropriate type information in function declarators]]

Non-Compliant Code Example (implicit return type)

Similarly, don't 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.

foo() {
  return UINT_MAX;
}

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

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

Compliant Solution (implicit return type)

unsigned int foo() {
  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 is rare, and the consequences are generally minor.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

DCL31-C

low

unlikely

medium

P2

L3

Related Vulnerabilities

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

References

[[ISO/IEC 9899-1999]] Section 6.7.2, "Type specifiers", Section 6.5.2.2, "Function calls"
[[Jones 08]]
[[MISRA 04]]


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

  • No labels