The C90 standard allows for C23 Standard requires type specifiers and forbids implicit function declarations. The C90 Standard allows 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, Consequently, some existing legacy code uses implicit typing. Some C compilers still support legacy code by allowing implicit typing, but it should not be used for new code. Such 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 C no longer allows 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 . The C Standard, 6.7.3 paragraph 2 [ ISO/IEC 9899:2024 ], states
Except where the type is inferred (6.7.
...
At 10), at least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each
struct
member declaration and type name.
This non-compliant noncompliant code example omits the type specifier.:
Code Block | ||||
---|---|---|---|---|
| ||||
extern foo;
|
Most C90 Some C implementations do not issue a diagnostic for the violation of this C99 constraint. Many C99 These nonconforming C translators will continue to treat such declarations as implying the type int
.
Compliant
...
Solution (Implicit int
)
This compliant solution explicitly declares foo
to be of type int
.includes a type specifier:
Code Block | ||||
---|---|---|---|---|
| ||||
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 C89C90, if a function is called without an explicit prototype, the compiler provides an implicit declaration.
The C90 Standard included the Standard [ISO/IEC 9899:1990] 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.
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 C90-compliant platforms assume an implicit declaration of extern int funcidentifier();
.
This declaration implies that the function may take any number and type of arguments and return an int
. However, to conform with C99, you to the current C Standard, programmers must explicitly prototype every function before invoking it. An implementation that conforms to the C Standard may or may not perform implicit function declarations, but C does require a conforming implementation to issue a diagnostic if it . This non-compliant example fails to prototype the foo()
function before invoking it in main()
encounters an undeclared function being used.
In this noncompliant code example, if malloc()
is not declared, either explicitly or by including stdlib.h
, a compiler that conforms only to C90 may implicitly declare malloc()
as int malloc()
. If the platform's size of int
is 32 bits, but the size of pointers is 64 bits, the resulting pointer would likely be truncated as a result of the implicit declaration of malloc()
, returning a 32-bit integer.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stddef.h> /* #include <stdlib.h> is missing */ int main(void) { int c = foo(); printf("%d\n", c); return 0; } int foo(int a) {for (size_t i = 0; i < 100; ++i) { /* int malloc() assumed */ char *ptr = (char *)malloc(0x10000000); *ptr = 'a'; } return a0; } |
...
Implementation Details
When compiled with Microsoft Visual Studio 2013 for a 64-bit platform, this noncompliant code example will eventually cause an access violation when dereferencing ptr
in the loop.
Compliant Solution (
...
Implicit Function Declaration)
In this This compliant solution , a prototype for foodeclares malloc()
appears before the function invocation. by including the appropriate header file:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdlib.h> int foo(int); int main(void) { for int c(size_t i = foo(0); printf("%d\n", c); return 0; } int foo(int a) {0; i < 100; ++i) { char *ptr = (char *)malloc(0x10000000); *ptr = 'a'; } return a0; } |
For more information on function declarations see , see DCL07-AC. Include the appropriate type information in function declarators.
...
Noncompliant Code Example (
...
Implicit Return Type)
Similarly, do Do not declare a function with implicit an implicit return type. If it returns For example, if a function returns a meaningful integer value, declare it it as returning int
. If it returns no meaningful value, declare it it as returning void
.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> #include <stdio.h> foo(void) { return UINT_MAX; } int main(void) { long long int c = foo(); printf("%lld\n", c); return 0; } |
Because the compiler assumes that foo()
returns a value of type int
for this noncompliant code example, UINT_MAX
is incorrectly converted to -1 −1
.
Compliant Solution (
...
Implicit Return Type)
This compliant solution explicitly defines the return type of foo()
as unsigned int
. As a result, the function correctly returns
.UINT_MAX
Code Block | ||||
---|---|---|---|---|
| ||||
#include <limits.h> #include <stdio.h> unsigned int foo(void) { return UINT_MAX; } int main(void) { long long int c = foo(); printf("%lld\n", c); return 0; } |
Risk Assessment
Because implicit declarations lead to less stringent type checking, they can introduce unexpected and erroneous behavior. Occurrences of an omitted type specifier in existing code are rare, and the consequences are generally minor, at worst usually causing 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 | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| type-specifier function-return-type implicit-function-declaration undeclared-parameter | Fully checked | ||||||
Axivion Bauhaus Suite |
| CertC-DCL31 | Fully implemented | ||||||
Clang |
| -Wimplicit-int | |||||||
Compass/ROSE | |||||||||
Coverity |
| MISRA C 2012 Rule 8.1 | Implemented | ||||||
Cppcheck Premium |
| premium-cert-dcl31-c | Partially Implemented Can detect implicit int | ||||||
| CC2.DCL31 | Fully implemented | |||||||
GCC |
| Can detect violations of this rule when the | |||||||
Helix QAC |
| C0434, C2050, C2051, C3335 | Fully implemented | ||||||
Klocwork |
| CWARN.IMPLICITINT | Fully implemented | ||||||
LDRA tool suite |
| 24 D, 41 D, 20 S, 326 S, 496 S | Fully implemented | ||||||
Parasoft C/C++test |
| CERT_C-DCL31-a | All functions shall be declared before use | ||||||
PC-lint Plus |
| 601, 718, 746, 808 | Fully supported | ||||||
Polyspace Bug Finder |
| Checks for:
Rule fully covered. | |||||||
PVS-Studio |
| V1031 | |||||||
SonarQube C/C++ Plugin |
| S819, S820 | Partially implemented; implicit return type not covered. | ||||||
RuleChecker |
| type-specifier function-return-type implicit-function-declaration undeclared-parameter | Fully checked | ||||||
TrustInSoft Analyzer |
| type specifier missing | Partially verified (exhaustively detects undefined behavior). |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
...
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
---|---|---|
CERT C Secure Coding Standard | DCL07-C. Include the appropriate type information in function declarators | Prior to 2018-01-12: CERT: Unspecified Relationship |
ISO/IEC TR 24772:2013 | Subprogram Signature Mismatch [OTR] | Prior to 2018-01-12: CERT: Unspecified Relationship |
MISRA C:2012 | Rule 8.1 (required) | Prior to 2018-01-12: CERT: Unspecified Relationship |
Bibliography
...
...
...
...
...
:2024] | Subclause 6.7. |
...
3, |
...
"Type Specifiers" | |
[Jones 2008] |
...
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