Functions should always be declared with the appropriate function prototype. If a function prototype is not available, the compiler cannot perform checks on the number and type of arguments being passed to functions. Argument type checking in C is only performed during compilation, and does not occur during linking, or dynamic loading.
Non-Compliant Code Example 1
This non-compliant program makes use of function declarators with empty parentheses. Consequently, the program compiles cleanly at high warning levels but contains serious errors.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> extern char *strchr(); int main(void) { char *c = strchr(12, 5); printf("Hello %c!\n", *c); } |
Section 6.11 of the C99 standards, "Future language directions", states that "The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature." The use of these declarations prevents the compiler from performing type checking.
Compliant Solution 1
The following compliant solution includes the header file containing the appropriate library function prototype.
Code Block | ||
---|---|---|
| ||
#include <stdio.h> #include <string.h> int main(void) { char *c = strchr("world", 'w'); printf("Hello %c!\n", *c); } |
Non-Compliant Code Example 2
The non-compliant code example uses the identifier-list form for the parameter declarations.
Code Block | ||
---|---|---|
| ||
extern int max(a, b) int a, b; { return a > b ? a : b; } |
Section 6.11 of the C99 standards, "Future language directions", states that "The use of function definitions with separate parameter identifier and declaration lists (not prototype-format parameter type and identifier declarators) is an obsolescent feature."
Compliant Solution 2
In this compliant solution, extern
is the storage-class specifier and int
is the type specifier; max(int a, int b)
is the function declarator; and the block within {} is the function body.
Code Block | ||
---|---|---|
| ||
extern int max(int a, int b) { return a > b ? a : b; } |
Non-Compliant Code Example 3
Failure to specify function prototypes results in a function being implicitly defined. Without a function prototype, the compiler assumes the the correct number and type of parameters have been supplied to a function. This can result in unintended and undefined behavior.
In this non-compliant code example, the definition of func()
expects three parameters but is supplied only two. However, because there is no prototype for func()
, the compiler assumes that the correct number of arguments has been supplied, and uses the next value on the program stack as the missing third argument.
Code Block | ||
---|---|---|
| ||
func(1, 2); /* ... */ int func(int one, int two, int three){ printf("%d %d %d", one, two, three); return 1; } |
Wiki Markup |
---|
C99 eliminated implicit function declarations from the C language \[[ISO/IEC 9899-1999:TC2|AA. C References#ISO/IEC 9899-1999TC2]\]. However, many compilers allow compilation of programs containing implicitly defined functions, although they may issue a warning message. These warnings should be resolved \[[MSC00-A. Compile cleanly at high warning levels]\], but do not prevent program compilation. |
Compliant Solution 3
To correct this example, the appropriate function prototype for func()
should be specified.
Code Block | ||
---|---|---|
| ||
int func(int, int, int); /* ... */ func(1, 2); /* ... */ int func(int one, int two, int three){ printf("%d %d %d", one, two, three); return 1; } |
Non-Compliant Code Example 4
Wiki Markup |
---|
The following example is based on rule \[[MEM02-A. Do not cast the return value from malloc()]\]. The header file {{stdlib.h}} contains the function prototype for {{malloc()}}. Failing to include {{stdlib.h}} causes an unintended version of {{malloc()}} to be called. |
Code Block | ||
---|---|---|
| ||
char *p = malloc(10); |
Compliant Solution 4
Including stdlib.h
ensures the function prototype for malloc()
is declared.
Code Block | ||
---|---|---|
| ||
#include <stdlib.h> /* ... */ char *p = malloc(10); |
Risk Assessment
Failing to specify function prototypes can result in unexpected or unintended program behavior.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL31-C | 1 (low) | 1 (unlikely) | 3 (low) | P3 | L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[ISO/IEC 9899-1999:TC2|AA. C References#ISO/IEC 9899-1999TC2]\] Forward, Section 6.9.1, "Function definitions" \[[Spinellis 06|AA. C References#Spinellis 06]\] Section 2.6.1, "Incorrect Routine or Arguments" |