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

Compare with Current View Page History

« Previous Version 154 Next »

Do not call a function with the wrong number or type of arguments. 

The C Standard identifies five distinct situations in which undefined behavior (UB) may arise as a result of invoking a function using a declaration that is incompatible with its definition or 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 a 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 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 type-generic macros for math functions. Although most functions from the <math.h> header have a complex counterpart in <complex.h>, several functions do not. Calling any of the following type-generic functions with complex values is undefined behavior.

Functions That Should Not Be Called with Complex Values

atan2()erf()fdim()fmin()ilogb()llround()logb()nextafter()rint()tgamma()
cbrt()erfc()floor()fmod()ldexp()log10()lrint()nexttoward()round()trunc()
ceil()exp2()fma()frexp()lgamma()log1p()lround()remainder()scalbn() 
copysign()expm1()fmax()hypot()llrint()log2()nearbyint()remquo()scalbln() 

 

This noncompliant code example attempts to take the base-2 logarithm of a complex number, resulting in undefined behavior:

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

Compliant Solution (Complex Number)

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

#include <tgmath.h>
 
void func(void) {
  double complex c = 2.0 + 4.0 * I;
  double complex result = log(c)/log(2);
}

Compliant Solution (Real Number)

The programmer can use this compliant solution if the intent is to take the base-2 logarithm of the real part of the complex number:

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

Noncompliant Code Example

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

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.

See undefined behavior 26.

#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 compliant solution, the function pointer fp, which points to the C standard library function strchr(), is declared with the correct parameters and is invoked with the correct number and type of arguments:

#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:

/* In another source file */
long f(long x) {
  return x < 0 ? -x : x;
}

/* In this source file, no f prototype in scope */
long f();
 
long g(int x) {
  return f(x);
}

Compliant Solution

In this compliant solution, the prototype for the function f() is included in the source file in the scope of where it is called, and the function f() is correctly called with an argument of type long:

/* In another source file */
 
long f(long x) {
  return x < 0 ? -x : x;
}

/* f prototype in scope in this source file */

long f(long x); 

long g(int x) {
  return f((long)x);  
}

Noncompliant Code Example (POSIX)

The POSIX function open() [IEEE Std 1003.1:2013] is a variadic function with the following prototype:

int open(const char *path, int oflag, ... );

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 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() is accidentally omitted:

fd = open(ms, O_CREAT | O_EXCL | O_WRONLY | O_TRUNC);

Note that, technically, it is incorrect to pass a third argument to open() when not creating a new file (that is, with the O_CREAT flag not set).

Compliant Solution (POSIX)

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

#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 */
  }
}

Risk Assessment

Calling a function with incorrect arguments can result in unexpected or unintended program behavior.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXP37-C

Medium

Probable

High

P4

L3

Automated Detection

ToolVersionCheckerDescription
CodeSonar8.1p0

LANG.FUNCS.APM

Array parameter mismatch
Compass/ROSE  

Can detect some violations of this rule. In particular, it ensures that all calls to open() supply exactly two arguments if the second argument does not involve O_CREAT, and exactly three arguments if the second argument does involve O_CREAT

ECLAIR

1.2

CC2.EXP37

Partially implemented

EDG   
Fortify SCA5.0  
GCC4.3.5 

Can detect violation of this rule when the -Wstrict-prototypes flag is used. However, it cannot detect violations involving variadic functions, such as the open() example described earlier

LDRA tool suite

9.7.1

41 D, 21 S, 98 S, 170 S, 496 S, 576 S

Partially implemented
Polyspace Bug FinderR2016a

Declaration mismatch,
Qualifier removed in conversion,
Standard function call with incorrect arguments,
Format string specifiers and arguments mismatch,
Unreliable cast of function pointer

Mismatch between function or variable declarations

Variable qualifier is lost during conversion

 

Argument to a standard function does not meet requirements for use in the function

 

String specifiers do not match corresponding arguments

Function pointer cast to another function pointer with different argument or return type


PRQA QA-C
Unable to render {include} The included page could not be found.
1331, 1332, 1333, 3002, 3320, 3335Partially implemented
SonarQube C/C++ Plugin3.11S930Detects incorrect argument count

Related Vulnerabilities

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

Related Guidelines

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

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
CWE-686, Function Call with Incorrect Argument Type

Bibliography

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

 


  • No labels