Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

The C Standard identifies five distinct situations in which undefined behavior may arise as a result of invoking a function using a declaration that is incompatible with its definition or with by supplying incorrect types or numbers of arguments:

UBDescription

26

A pointer is used to call a function whose type is not compatible with the referenced type (6.3.2.3).

38

For a call to a function without a function prototype in scope, the number of arguments does not equal the number of parameters (6.5.2.2).

39

For call to a function without a function prototype in scope where the function is defined with a function prototype, either the prototype ends with an ellipsis or the types of the arguments after promotion are not compatible with the types of the parameters (6.5.2.2).

40

For a call to a function without a function prototype in scope where the function is not defined with a function prototype, the types of the arguments after promotion are not compatible with those of the parameters after promotion (with certain exceptions) (6.5.2.2).

41

A function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function (6.5.2.2).

Functions that are appropriately declared (as in DCL40-C. Do not create incompatible declarations of the same function or object) will typically generate a compiler error if compiler diagnostic message if they are supplied with the wrong number or types of arguments. However, there are cases in which supplying the incorrect arguments to a function will, at best, generate compiler warnings. Although such warnings should be resolved, they do not prevent program compilation. (See MSC00-C. Compile cleanly at high warning levels.)

Noncompliant Code Example

The header tgmath.h provides header <tgmath.h> provides type-generic macros for math functions. Although most functions from the math.h header the <math.h> header have a complex counterpart in complexin <complex.hh>, several functions do not. Calling any of the following type-generic functions with complex values results in undefined behavior.

...

If the clog2() function is not available for your an implementation as an extension, you the programmeng can take the base-2 logarithm of a complex number using log() instead of log2(), as because log() can be used on complex arguments, as shown in this compliant solution:

...

Compliant Solution (Real Number)

This The programmer can use this compliant solution can be used if the programmer's intent was is to take the base-2 logarithm of the real part of the complex number:

Code Block
bgColor#ccccff
langc
#include <tgmath.h>
 
void func(void) {
  double complex c = 2.0 + 4.0 * I;
  double complex result = log2(creal(c));
}

...

In this noncompliant example, the C standard library function strchr() is called through the function pointer fp with declared with a prototype with incorrectly typed arguments. According to the C Standard, subclause 6.3.2.3, paragraph 8 [ISO/IEC 9899:2011],

...

Code Block
bgColor#FFCCCC
langc
#include <stdio.h>
#include <string.h>

char *(*fp)();

int main(void) {
  const char *c;
  fp = strchr;
  c = fp('e', "Hello");
  printf("%s\n", c);
  return 0;
}

...

Compliant Solution

In this noncompliant examplecompliant solution, the function pointer fp, which points to the C standard library function strchr(), is declared with the correct arguments. This code still exhibits the same undefined behavior, but most compilers will warn that the arguments passed to fp do not match its declaration.

Code Block
bgColor#FFCCCC
langc
#include <stdio.h>
#include <string.h>

char *(*fp)(const char *, int);
int main(void) {
  const char *c;
  fp = strchr;
  c = fp('e', "Hello");
  printf("%s\n", c);
  return 0;
}

Compliant Solution

In this compliant solution, the function pointer fp is parameters and is invoked with the correct number and type of arguments:

Code Block
bgColor#ccccff
langc
#include <stdio.h>
#include <string.h>

char *(*fp)(const char *, int);

int main(void) {
  const char *c;
  fp = strchr;
  c = fp("Hello",'e');
  printf("%s\n", c);
  return 0;
}

Noncompliant Code Example

In this noncompliant example, the function f() is defined to take an argument of type long but f() is called from another file with an argument of type int:

...

The open() function accepts a third argument to determine a newly created file's access mode. If open() is used to create a new file, and the third argument is omitted, the file may be created with unintended access permissions . (See see FIO06-C. Create files with appropriate access permissions).)

In this noncompliant code example from a vulnerability in the useradd() function of the shadow-utils package CVE-2006-1174, the third argument to open() has been is accidentally omitted:

Code Block
bgColor#ffcccc
langc
fd = open(ms, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC);

Note that, technically, it is also incorrect to pass a third argument to open() when not creating a new file (that is, with the O_CREAT flag not set). A POSIX implementation could, if it wished, return an EINVAL error in this case. However, in practice, it is unlikely to cause a problem.

Compliant Solution (POSIX)

To correct In this examplecompliant solution, a third argument is specified in the call to open():

Code Block
bgColor#ccccff
langc
#include <fcntl.h>
 
void func(const char *ms, mode_t perms) {
  /* ... */
  int fd;
  fd = open(ms, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC, perms);
  if (fd == -1) {
    /* Handle error */
  }
}

...

CERT C Secure Coding Standard

DCL07-C. Include the appropriate type information in function declarators
MSC00-C. Compile cleanly at high warning levels
FIO06-C. Create files with appropriate access permissions

CERT C++ Secure Coding StandardEXP37-CPP. Call variadic functions with the arguments intended by the API
ISO/IEC TR 24772:2013Subprogram Signature Mismatch [OTR]
ISO/IEC TS 17961Calling functions with incorrect arguments [argcomp]
MISRA C:2012Rule 8.2 (required)
Rule 17.3 (mandatory)
MITRE CWE

CWE-628, Function call with incorrectly specified arguments
Function call with incorrect argument typeCall with Incorrectly Specified Arguments
CWE-686, Function Call with Incorrect Argument Type

Bibliography

[CVE]CVE-2006-1174
[ISO/IEC 9899:2011]Subclause 6.3.2.3, "Pointers"
Subclause 6.5.2.2, "Function Calls"
[IEEE Std 1003.1:2013]open()
[Spinellis 2006]Section 2.6.1, "Incorrect Routine or Arguments"

...