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.
#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.
#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.
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.
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.
func(1, 2); /* ... */ int func(int one, int two, int three){ printf("%d %d %d", one, two, three); return 1; }
C99 eliminated implicit function declarations from the C language [[ISO/IEC 9899-1999:TC2]]. 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.
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
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 malloc()
to be improperly defined.
char *p = malloc(10);
Compliant Solution 4
Including stdlib.h
ensures the function prototype for malloc()
is declared.
#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
[[ISO/IEC 9899-1999:TC2]] Forward, Section 6.9.1, "Function definitions"
[[Spinellis 06]] Section 2.6.1, "Incorrect Routine or Arguments"