Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated UB references from C11->C23

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

The C Standard identifies two 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

25

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

37

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).

An application programming interface (API) specifies how a function is intended to be called. Calling a function with incorrect arguments can result in unexpected or unintended program behavior. Functions that are appropriately declared (see DCL07as in DCL40-C. Include the appropriate type information in function declarators) will typically fail compilation 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 where in which supplying the incorrect arguments to a function will, at best, generate compiler warnings. These Although such warnings should be resolved (see , they do not prevent program compilation. (See MSC00-C. Compile cleanly at high warning levels) but do not prevent program compilation.

Noncompliant Code Example (Function Pointers)

.)

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:

Code Block
bgColor#ffcccc
langc
#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:

Code Block
bgColor#ccccff
langc
#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:

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));
}

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:2024]

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 25In this example, the function pointer fp is used to refer to the function strchr(). However, fp is declared without a function prototype. As a result, there is no type checking performed on the call to fp(12,2);. A typedef is included for compatibility with DCL05-C. Use typedefs to improve code readability.

Code Block
bgColor#FFCCCC
langc

#include <stdio.h>
#include <string.h>

typedef char *(*noarg_fnfp) ();
noarg_fn fp;

int main(void) {
  const char *c;
  fp = strchr;
  c = fp(12'e', 2"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:Declaring fp with a function prototype corrects this example.

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

typedef char *(*twoarg_fnfp) (const char *, int);
twoarg_fn fp;

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

Noncompliant Code Example

...

Wiki Markup
The POSIX function {{open()}} \[[Open Group 04|AA. C References#Open Group 04]\] is a variadic function with the following prototype:

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:

Code Block
bgColor#FFCCCC
langc
/* 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:

Code Block
bgColor#ccccff
langc
/* 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:

Code Block
Code Block

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 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 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 practise 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, file_access_permissionsperms);
  if (fd == -1) {
    /* Handle Errorerror */
}
/* ... */}
}

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

Medium

probable

Probable

high

High

P4

L3

Automated Detection

...

GCC Compiler 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 above.

...

ToolVersionCheckerDescription
Astrée
Include Page
Astrée_V
Astrée_V

incompatible-argument-type

parameter-match

parameter-match-computed

parameter-match-type

Fully checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-EXP37
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

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

Coverity
Include Page
Coverity_V
Coverity_V

MISRA C 2012 Rule 8.2

MISRA C 2012 Rule 17.3

Implemented

Relies on functions declared with prototypes, allow compiler to check

Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

premium-cert-exp37-cFully implemented

ECLAIR

Include Page
ECLAIR_V
ECLAIR_V

CC2.EXP37

Partially implemented

EDG


GCC
Include Page
GCC_V
GCC_V

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

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C1331, C1332, C1333, C3002, C3320, C3335

C++0403


Klocwork
Include Page
Klocwork_V
Klocwork_V
MISRA.FUNC.UNMATCHED.PARAMS
LDRA tool suite
Include Page
LDRA_V
LDRA_V

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

Partially implemented
Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_C-EXP37-a
CERT_C-EXP37-b
CERT_C-EXP37-d

Conversions shall not be performed between non compatible pointer to a function types
Specify the access permission bits if a file is created using the 'open' or 'openat' system call
Functions shall always have visible prototype at the function call

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule EXP37-C

Checks for:

  • Implicit function declaration
  • Bad file access mode or status
  • Unreliable cast of function pointer
  • Standard function call with incorrect arguments

Rule partially covered.

PVS-Studio

Include Page
PVS-Studio_V
PVS-Studio_V

V540, V541, V549, V575, V632, V639, V666, V671, V742, V743, V764, V1004
SonarQube C/C++ Plugin
Include Page
SonarQube C/C++ Plugin_V
SonarQube C/C++ Plugin_V
S930Detects incorrect argument count
RuleChecker

Include Page
RuleChecker_V
RuleChecker_V

parameter-match

parameter-match-type

Partially checked
TrustInSoft Analyzer

Include Page
TrustInSoft Analyzer_V
TrustInSoft Analyzer_V

unclassified ("function type matches")Partially verified (see one compliant and one non-compliant example).

Related Vulnerabilities

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

References

Wiki Markup
\[[CVE|AA. C References#CVE]\] [CVE-2006-1174 | http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2006-1174]
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Forward and Section 6.9.1, "Function definitions"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "OTR Subprogram Signature Mismatch"
\[[MISRA 04|AA. C References#MISRA 04]\] Rule 16.6
\[[Spinellis 06|AA. C References#Spinellis 06]\] Section 2.6.1, "Incorrect Routine or Arguments"

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

CERT C Secure Coding StandardDCL07-C. Include the appropriate type information in function declaratorsPrior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding StandardMSC00-C. Compile cleanly at high warning levelsPrior to 2018-01-12: CERT: Unspecified Relationship
CERT C Secure Coding StandardFIO06-C. Create files with appropriate access permissionsPrior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TR 24772:2013Subprogram Signature Mismatch [OTR]Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TS 17961Calling functions with incorrect arguments [argcomp]Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 8.2 (required)Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 17.3 (mandatory)Prior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11CWE-628, Function Call with Incorrectly Specified Arguments2017-07-05: CERT: Rule subset of CWE

CERT-CWE Mapping Notes

Key here for mapping notes

CWE-685 and EXP37-C

EXP37-C = Union( CWE-685, CWE-686) Intersection( CWE-685, CWE-686) = Ø

CWE-686 and EXP37-C

Intersection( EXP37-C, FIO47-C) =


  • Invalid argument types passed to format I/O function


EXP37-C – FIO47-C =


  • Invalid argument types passed to non-format I/O function


FIO47-C – EXP37-C =


  • Invalid format string, but correctly matches arguments in number and type


EXP37-C = Union( CWE-685, CWE-686)

Intersection( CWE-685, CWE-686) = Ø

CWE-628 and EXP37-C

CWE-628 = Union( EXP37-C, list) where list =


  • Improper ordering of function arguments (that does not violate argument types)



  • Wrong argument values or references


Bibliography

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


...

Image Added Image Added Image AddedEXP36-C. Do not convert pointers into more strictly aligned pointer types      03. Expressions (EXP)       EXP38-C. Do not call offsetof() on bit-field members or invalid types