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

Compare with Current View Page History

« Previous Version 81 Next »

The C Standard does not allow for implicit typing of variables and functions. The C90 Standard did allow such implicit typing.  Consequently, there exists some legacy code that uses implicit typing.  Some C compilers still support legacy code by allowing implicit typing, but it should not be used for new code.  Because implicit declarations lead to less stringent type checking, they can introduce unexpected and erroneous behavior or even security vulnerabilities.

The C 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)

C 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. Section 6.7.2 of the C Standard [ISO/IEC 9899:2011] 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:

extern foo;

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

Compliant Solution

This compliant solution explicitly includes a type specifier:

extern int foo;

Noncompliant Code Example (Implicit Function Declaration)

Implicit declaration of functions is not allowed: every function should 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 this 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.

If a function declaration is not visible at the point at which a call to the function is made, C90-compliant platforms assume an implicit declaration of

extern int func();

This implies that the function may take any number and type of arguments, and returns a single int.

However, to conform with C99, you must explicitly prototype every function before invoking it. An implementation that conforms to C99 or later may or may not perform implicit function declarations. However, C99 does require the implementation to issue a diagnostic if it encounters an undeclared function being used.

In the following noncompliant code example, if malloc() is not declared, either explicitly, or by including stdlib.h, a compiler may implicitly declare malloc() as int malloc(). (Compilers that only comply with C90 are required to provide an implicit declaration of malloc().)  If the platform's size of int is 32 bits, but the size of pointers is 64 bits, the resulting pointer could be truncated as a result of the implicit declaration of malloc() returning a 32-bit integer.

 

/* #include <stdlib.h> is missing */
 
int main(void) {
  size_t i;
  for (i = 0; i < 100; ++i) {
    char *ptr = (char*)malloc(0x10000000); /* int malloc() assumed */
    *ptr = 'a';
  }
  return 0;
}

When compiled with Microsoft Visual Studio (a C90-only platform), the above code will eventually cause an access violation when dereferencing ptr in the loop.

Compliant Solution (Implicit Function Declaration)

This compliant solution declares malloc() by including the appropriate header file.

#include <stdlib.h>
 
int main(void) {
  size_t i;
  for (i = 0; i < 100; ++i) {
    char *ptr = (char*)malloc(0x10000000); /* int malloc() assumed */
    *ptr = 'a';
  }
  return 0;
}

 

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.

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 explicitly defines the return type of foo() as unsigned int:

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

Tool

Version

Checker

Description

Compass/ROSE

 

 

 

ECLAIR

1.2

CC2.DCL31

Fully implemented

GCC

4.3.5

 

Can detect violations of this rule when the -Wimplicit and -Wreturn-type flags are used

Klocwork

2024.3

IF_MISS_DECL RETVOID.IMPLICIT

 

LDRA tool suite

9.7.1

24 D
20 S
326 S

Fully implemented

PRQA QA-C
Unable to render {include} The included page could not be found.

0434 (C)
1302
2050
2051
3335

Fully implemented

Related Vulnerabilities

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

Related Guidelines

ISO/IEC TR 24772:2013Subprogram Signature Mismatch [OTR]
MISRA C:2012 

Bibliography

[ISO/IEC 9899:2011]Section 6.7.2, "Type Specifiers"
[Jones 2008] 

 


  • No labels