Main Content

CWE Rule 233

Improper Handling of Parameters

Since R2026a

Description

The product does not properly handle when the expected number of parameters, fields, or arguments is not provided in input, or if those parameters are undefined.

Polyspace Implementation

The rule checker checks for these issues:

  • Incompatible argument

  • Declaration mismatch

  • Unreliable cast of function pointer

  • Standard function call with incorrect arguments

  • Function declaration mismatch

Examples

expand all

Issue

Incompatible argument occurs when an external function is called by using an argument that is not compatible with the prototype. The compatibility of types might depend on the set of hardware and software that you use. For instance, consider this code:


extern long foo(int);

long bar(long i) {
    return foo(i); //Noncompliant: calls foo(int) with a long              
}
The external function foo is called with a long when an int is expected. In environments where the size of an int is smaller than the size of a long, this function call is incompatible with the prototype, resulting in a defect.

Risk

Calling external functions with arguments that are incompatible with the parameter is undefined behavior. Depending on your environment, the code might compile but behave in an unexpected way.

Fix

When calling external functions, use argument types that are smaller or equal in size compared to the parameter type defined in the prototype. Check the sizes of various integer types in your environment to determine compatibility of argument and parameter types.

Example — Call External Functions with Incompatible argument

          
extern long foo1(int);
extern long foo2(long);
void bar(){
	int varI;
	long varL;
	foo1(varL);//Noncompliant
	foo2(varI);//Compliant
}

In this example, the external function foo1 is called with a long argument, while the prototype specifies the parameter as an int. In x86 architecture, the size of long is larger than the size of int. The call foo1(varL) might result in undefined behavior. Polyspace® flags the call. The call foo2(varI) uses an int argument while the parameter is specified as a long. This type of mismatch is compliant with this rule because the size of int is not larger than the size of long.

To run this example in Polyspace, use these options:

  • -lang c

  • -target x86_64

See Target processor type (-target).

Correction — Cast Variables Explicitly to Match Argument to Parameter

To fix this issue, cast the argument of foo1 explicitly so that argument type and parameter type matches.


          
extern long foo1(int);
extern long foo2(long);
void bar(){
	int varI;
	long varL;
	foo1((int)varL);//Compliant
	foo2(varI);//Compliant
}
Issue

Declaration mismatch occurs when a function or variable declaration does not match other instances of the function or variable.

Risk

When a mismatch occurs between two variable declarations in different compilation units, a typical linker follows an algorithm to pick one declaration for the variable. If you expect a variable declaration that is different from the one chosen by the linker, you can see unexpected results when the variable is used.

A similar issue can occur with mismatch in function declarations.

Fix

The fix depends on the type of declaration mismatch. If both declarations indeed refer to the same object, use the same declaration. If the declarations refer to different objects, change the names of the one of the variables. If you change a variable name, remember to make the change in all places that use the variable.

Sometimes, declaration mismatches can occur because the declarations are affected by previous preprocessing directives. For instance, a declaration occurs in a macro, and the macro is defined on one inclusion path but undefined in another. These declaration mismatches can be tricky to debug. Identify the divergence between the two inclusion paths and fix the conflicting macro definitions.

If you do not want to fix the issue, add comments to your result or code to avoid another review. See:

Example - Inconsistent Declarations in Two Files

file1.c


          int foo(void) { //Noncompliant
    return 1;
}

file2.c


          
          double foo(void);

int bar(void) {
    return (int)foo();
}

In this example, file1.c declares foo() as returning an integer. In file2.c, foo() is declared as returning a double. This difference might cause a compilation failure. Polyspace raises a defect on the second instance of foo in file2.

Correction — Align the Function Return Values

One possible correction is to change the function declarations so that they match. In this example, by changing the declaration of foo in file2.c to match file1.c, the defect is fixed.

file1.c


          int foo(void) {
    return 1;
}

file2.c


          int foo(void);

int bar(void) {
    return foo();
}
Example - Inconsistent Structure Alignment

test1.c


                    #include "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

test2.c


                    
                    #include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square; //Noncompliant

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

circle.h


                    #pragma pack(1)

extern struct aCircle{ 
    int radius; 
} circle; 

square.h


                    extern struct aSquare { 
    unsigned int side:1; 
} square; 

In this example, a declaration mismatch defect is raised on square in square.h because Polyspace infers that square in square.h does not have the same alignment as square in test2.c. This error occurs because the #pragma pack(1) statement in circle.h declares specific alignment. In test2.c, circle.h is included before square.h. Therefore, the #pragma pack(1) statement from circle.h is not reset to the default alignment after the aCircle structure. Because of this omission, test2.c infers that the aSquare square structure also has an alignment of 1 byte. This defect might cause a compilation failure.

Correction — Close Packing Statements

One possible correction is to reset the structure alignment after the aCircle struct declaration. For the GNU® or Microsoft® Visual compilers, fix the defect by adding a #pragma pack() statement at the end of circle.h.

test1.c


                    #include "square.h" 
#include "circle.h" 
struct aCircle circle; 
struct aSquare square;

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

test2.c


                    #include "circle.h" 
#include "square.h" 
struct aCircle circle; 
struct aSquare square;

int main(){ 
    square.side=1; 
    circle.radius=1;
    return 0;
}

circle.h


                    #pragma pack(1)

extern struct aCircle{ 
    int radius; 
} circle; 

#pragma pack()

square.h


                    extern struct aSquare { 
    unsigned int side:1; 
} square;

Other compilers require different #pragma pack syntax. For your syntax, see the documentation for your compiler.

Correction — Use the Ignore pragma pack directives Option

One possible correction is to add the Ignore pragma pack directives option to your Bug Finder analysis. If you want the structure alignment to change for each structure, and you do not want to see this Declaration mismatch defect, use this correction.

  1. Open the configuration for your Polyspace Platform project. Navigate to the Static Analysis tab and select the Advanced node.

  2. In the Other section, add an empty row and enter -ignore-pragma-pack.

  3. Rerun your analysis.

    The Declaration mismatch defect is resolved.

Issue

This issue occurs when a function pointer is cast to another function pointer that has different argument or return type.

Risk

If you cast a function pointer to another function pointer with different argument or return type and then use the latter function pointer to call a function, the behavior is undefined.

Fix

Avoid a cast between two function pointers with mismatch in argument or return types.

See examples of fixes below.

If you do not want to fix the issue, add comments to your result or code to avoid another review. See:

Example — Unreliable cast of function pointer error

          #include <stdio.h>
#include <math.h>
#define PI 3.142
 
double Calculate_Sum(int (*fptr)(double))
{
    double  sum = 0.0;
    double  y;
	  
    for (int i = 0;  i <= 100;  i++)
    {
        y = (*fptr)(i*PI/100);
        sum += y;
    }
    return sum / 100;
}
 
int main(void)
{
    double  (*fp)(double);      
    double  sum;
 
    fp = sin;
    sum = Calculate_Sum(fp);  //Noncompliant
    /* Defect: fp implicitly cast to int(*) (double) */

    printf("sum(sin): %f\n", sum);
    return 0;
}

The function pointer fp is declared as double (*)(double). However in passing it to function Calculate_Sum, fp is implicitly cast to int (*)(double).

Correction — Avoid Function Pointer Cast

One possible correction is to check that the function pointer in the definition of Calculate_Sum has the same argument and return type as fp. This step makes sure that fp is not implicitly cast to a different argument or return type.


          #include <stdio.h>
#include <math.h>
# define PI 3.142
 
/*Fix: fptr has same argument and return type everywhere*/
double Calculate_Sum(double (*fptr)(double)) 
{
    double  sum = 0.0;
    double y;
	    
    for (int i = 0;  i <= 100;  i++)
    {
        y = (*fptr)(i*PI/100);
        sum += y;
    }
    return sum / 100;
}
 
int main(void)
{
    double  (*fp)(double);      
    double  sum;
 
    
    fp = sin;
    sum = Calculate_Sum(fp);
    printf("sum(sin): %f\n", sum);
 
    return 0;
}
Issue

This issue occurs when the arguments to certain standard functions do not meet the requirements for their use in the functions.

For instance, the arguments to these functions can be invalid in the following ways.

Function TypeSituationRiskFix
String manipulation functions such as strlen and strcpyThe pointer arguments do not point to a NULL-terminated string.The behavior of the function is undefined.Pass a NULL-terminated string to string manipulation functions.
File handling functions in stdio.h such as fputc and freadThe FILE* pointer argument can have the value NULL.The behavior of the function is undefined.Test the FILE* pointer for NULL before using it as function argument.
File handling functions in unistd.h such as lseek and read The file descriptor argument can be -1.

The behavior of the function is undefined.

Most implementations of the open function return a file descriptor value of -1. In addition, they set errno to indicate that an error has occurred when opening a file.

Test the return value of the open function for -1 before using it as argument for read or lseek.

If the return value is -1, check the value of errno to see which error has occurred.

The file descriptor argument represents a closed file descriptor.The behavior of the function is undefined.Close the file descriptor only after you have completely finished using it. Alternatively, reopen the file descriptor before using it as function argument.
Directory name generation functions such as mkdtemp and mkstempsThe last six characters of the string template are not XXXXXX.The function replaces the last six characters with a string that makes the file name unique. If the last six characters are not XXXXXX, the function cannot generate a unique enough directory name.Test if the last six characters of a string are XXXXXX before using the string as function argument.
Functions related to environment variables such as getenv and setenvThe string argument is "".The behavior is implementation-defined.Test the string argument for "" before using it as getenv or setenv argument.
The string argument terminates with an equal sign, =. For instance, "C=" instead of "C".The behavior is implementation-defined.Do not terminate the string argument with =.
String handling functions such as strtok and strstr

  • strtok: The delimiter argument is "".

  • strstr: The search string argument is "".

Some implementations do not handle these edge cases.Test the string for "" before using it as function argument.

Fix

The fix depends on the root cause of the defect. See fixes in the table above and code examples with fixes below.

If you do not want to fix the issue, add comments to your result or code to avoid another review. See:

Example — NULL Pointer Passed as strnlen Argument
#include <string.h>
#include <stdlib.h>

enum {
    SIZE10 = 10,
    SIZE20 = 20
};

int func() {
    char* s = NULL;
    return strnlen(s, SIZE20); //Noncompliant
}

In this example, a NULL pointer is passed as strnlen argument instead of a NULL-terminated string.

Before running analysis on the code, specify a GNU compiler. See Compilation toolchain (Static analysis).

Correction — Pass NULL-terminated String

Pass a NULL-terminated string as the first argument of strnlen.

#include <string.h>
#include <stdlib.h>

enum {
    SIZE10 = 10,
    SIZE20 = 20
};

int func() {
    char* s = "";
    return strnlen(s, SIZE20);
}
Issue

Function declaration mismatch occurs when the prototype of a function does not match its definition. If a function lacks a prototype in the file where it is called, Polyspace deduces its prototype based on the signature of the call. If the deduced prototype does not match the definition of the function, Polyspace raises this defect. The prototype of a variadic function cannot be deduced from its function call. If you call a variadic function without specifying its prototype in the same file, Polyspace raises this defect.

When deducing the prototype of a function from a call to such a function, Polyspace makes these assumptions:

  • The number of arguments of the deduced prototype is equal to the input argument of the function call.

  • The argument types of the deduced prototype are set by implicitly promoting the argument types of the function call. For instance, both signed and unsigned char or short type arguments are promoted to int. Similarly float type arguments are promoted to double.

  • Type mismatch between the arguments of the function definition and the function prototype might depend on your environment. Polyspace considers two types as compatible if they have the same size and signedness in the environment that you use. For instance, if your specify -target as i386, Polyspace considers long and int as compatible types.

The checker does not flag this issue in a default Polyspace as You Code™ analysis. See Checkers Deactivated in Polyspace as You Code Analysis (Polyspace as You Code).

Risk

According to the C standard, function declaration mismatch might result in undefined behavior even though such code might compile successfully producing only warnings during compilation. Because code with this issue might compile successfully, function declaration mismatches might result in unexpected results that are difficult to diagnose.

Fix

  • Before you call a function, provide its complete prototype, even if you define the function later in the same file.

  • Avoid any mismatch between the number arguments in the function prototype declaration and the function definition.

  • Avoid any mismatch between the argument types of the function prototype declaration and the function definition.

When complete prototypes of the called functions are provided, the compiler tries to resolve any function declaration mismatches through implicit casting. If the compiler fails to resolve the mismatch, the compilation fails, which prevents unexpected behavior. To fix such compile errors, call the functions using argument types and numbers that match the function definition.

Example — Function Calls That Lack Prototypes

                    
                    // file1.c
void foo(int iVar){
	//...
}
void bar(float fVar1, float fVar2){
	//...
}
void bar2(float fVar1){
	//...
}
void fubar(const char* str,...){
	//...
}
void foo2(char cVar){
	//...
}
void call_variadic(){
	fubar("String");
}

                    
                    //file2.c
void bar2(float);
void foo2(int);
void call_funcs(){
	int iTemp;
	float fTemp;
	foo();//Noncompliant
	bar(fTemp,fTemp);//Noncompliant
	fubar("String"); //Noncompliant	
	bar2(iTemp);//Compliant
	foo2(iTemp); //Noncompliant
}

In this example, the functions foo, foo2, bar, bar2, and fubar are defined in the file file1.c. These functions are then called in the file file2.c.

  • The function foo is defined in file1.c with one int input and called in file2.c without any input. Because file2.c does not have a prototype for foo, Polyspace deduces a prototype based on the call foo(), which takes no input. This deduced prototype does not match the function declaration in file1.c. Polyspace flags the call.

  • The function bar is defined in file1.c with two float inputs and called in file2.c with two float inputs. Because file2.c does not have a prototype for bar, Polyspace deduces a prototype based on the call bar(fTemp,fTemp). By promoting the argument types of the function call, the signature of this deduced prototype is bar(double, double), which does not match the function declaration in file1.c. Polyspace flags the call.

  • The function bar2 is defined in file1.c with one float input. The complete prototype for bar2, which matches the definition, is provided in file2.c. Because a complete prototype is present in this file, when bar2 is called with an incorrect input, the compiler implicitly converts the int input iTemp into a float. Because the call to the function matches the declaration after an implicit conversion facilitated by the prototype, Polyspace does not flag the call.

  • The function foo2 is defined in file1.c with a char input. Its prototype in file2.c is defined with a int input. Because the definition and the prototype do not match, Polyspace flags the call to foo2.

  • The variadic function fubar is defined in file1.c. The call to it in call_variadic is compliant because the call comes after the definition. The function fubar does not have a prototype in file2.c. Because the function takes a variable number of inputs, its prototype cannot be deduced. The call to fubar in file2.c lacks a prototype and Polyspace flags the call.

Correction — Compliant Function Calls

The fix for this defect is to declare complete prototypes for the called functions in all compilation modules. It is a best practice to combine the function prototype declarations in a header file, and then include it in files where the functions are called. In this case, resolve the flagged issues by including such a header file prototype.h in file2.c. Once a correct prototype is declared, the call foo() in file2.c causes a compilation failure because the compiler cannot resolve the mismatch between the call and the declared prototype. Call foo with an int to resolve the compilation failure.


                    
                    // file1.c
void foo(int iVar){
	//...
}
void bar(float fVar1, float fVar2){
	//...
}
void bar2(float fVar1){
	//...
}
void fubar(const char* str,...){
	//...
}
void foo2(char cVar){
	//...
}
void call_variadic(){
	fubar("String");
}

                    
                    //prototypes.h
void foo(int iVar);
void bar(float fVar1, float fVar2);
void fubar(const char* str,...);
void bar2(float);
void foo2(char);
void call_variadic(void);
void call_funcs(void);

                    
                    //file2.c
#include"prototype.h"
void call_funcs(){
	int iTemp;
	float fTemp;
	//foo(); This call results in compile failure
	foo(iTemp);//Compliant
	bar(fTemp,fTemp);//Compliant
	fubar("String"); //Compliant	
	bar2(iTemp);//Compliant
	foo2('a'); //Compliant
}

Check Information

Category: Data Processing Errors
PQL Name: std.cwe_native.R233

Version History

Introduced in R2026a