parts/6.34.SupprogramSignatureMismatch-OTR.md

6.34 Subprogram Signature Mismatch [OTR]

6.34.1 Applicability to language

In general, there must be a match between the number of parameters in a function call and the number of arguments in the function definition. For issues related to macro signatures, see subclause Pre-processor directives[NMP].

The number of arguments can be different to the number of parameters in a function where: - a function template includes a function parameter pack, or - a function parameter includes a default argument, or - a function parameter-declaration-clause ends with an ellipsis, f(\...).

Calling a function template with a function parameter pack results in a specialization of the function with the parameter types matching the corresponding argument types.

The compiler will ensure for variadic templates that the type and number of arguments is correct.

A call to a function with default arguments can provide fewer arguments than parameters as long as the parameters for which no explicit argument is provided include a default argument.

Where a function parameter-declaration-clause ends with an ellipsis, additional arguments can be accessed through the mechanisms provided by <cstdarg>. No information about the number or types of the parameters is supplied by the compiler. The use of this feature outside of special situations can be the basis for vulnerabilities.

Undefined behavior can arise, for example:

    #include <cstdarg>

void f1 (int cnt, ...)
{
  va_list ap;
  va_start (ap, cnt);

  short i = va_arg (ap, short);  // Invalid type

  va_end(ap);
}
#include <cstdarg>

void f1 (int cnt, ...)
{
  va_list ap;
  va_start (ap, cnt);

  int i = va_arg (ap, int);
  int j = va_arg (ap, int);

  va_end(ap);
}

void f2 ()
{
  f1 (1, 2, 3);  // OK
  f1 (1, 2);     // results in undefined behaviour
}

These issues cannot occur where default arguments or variadic function templates are used.

The C++ Name mangling ensures that function signatures match accross translation units.

This does not apply to other mangling schemes. For example, parameters do not form part of the mangled name for functions declared with the extern "C" linkage specification. Thus such a function can be invoked with incorrect parameter types due to an incorrect redeclaration of the function:

// library.cc
extern "C" void foo (unsigned, unsigned)
{
  // ...
}
// main.cc

extern "C" void foo (unsigned);

int main ()
{
  foo (0xffffffff);  // Calling function that is
                     // defined to take 2 parameters
}

6.34.2 Avoidance mechanisms for language users

To avoid the vulnerability or mitigate its ill effects, C++ software developers can:

Note: See also C++ Core Guidelines F.55.