CWE Rule 686
Description
Rule Description
The software calls a function, procedure, or routine, but the caller specifies an argument that is the wrong data type, which may lead to resultant weaknesses.
Polyspace Implementation
The rule checker checks for these issues:
Bad file access mode or status
Incorrect data type passed to va_arg
Standard function call with incorrect arguments
Use of automatic variable as putenv-family function argument
Writing to const qualified object
Examples
Bad file access mode or status
This issue occurs
when you use functions in the fopen
or
open
group with invalid or
incompatible file access modes, file creation flags, or file
status flags as arguments. For instance, for the
open
function, examples of valid:
Access modes include
O_RDONLY
,O_WRONLY
, andO_RDWR
File creation flags include
O_CREAT
,O_EXCL
,O_NOCTTY
, andO_TRUNC
.File status flags include
O_APPEND
,O_ASYNC
,O_CLOEXEC
,O_DIRECT
,O_DIRECTORY
,O_LARGEFILE
,O_NOATIME
,O_NOFOLLOW
,O_NONBLOCK
,O_NDELAY
,O_SHLOCK
,O_EXLOCK
,O_FSYNC
,O_SYNC
and so on.
The defect can occur in the following situations.
Situation | Risk | Fix |
---|---|---|
You pass an empty or invalid
access mode to the
According to the
ANSI® C standard, the valid access
modes for
|
Some implementations allow extension of the access mode such as:
However, your access mode string must begin with one of the valid sequences. | Pass a valid access mode to
fopen . |
You pass the status flag
O_APPEND to the
open function without
combining it with either
O_WRONLY or
O_RDWR . |
The
| Pass either
O_APPEND|O_WRONLY or
O_APPEND|O_RDWR as
access mode. |
You pass the status flags
O_APPEND and
O_TRUNC together to
the open
function. |
The
| Depending on what you intend to do, pass one of the two modes. |
You pass the status flag
O_ASYNC to the
open function. | On certain implementations, the mode
O_ASYNC does not
enable signal-driven I/O
operations. | Use the fcntl(pathname,
F_SETFL, O_ASYNC);
instead. |
The fix depends on the function and the flags used. 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:
Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface.
Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser.
Annotate Code and Hide Known or Acceptable Results if you review results in an IDE.
#include <stdio.h> void func(void) { FILE *file = fopen("data.txt", "rw"); //Noncompliant if(file!=NULL) { fputs("new data",file); fclose(file); } }
In this example, the access mode rw
is invalid.
Because r
indicates that you open the file for
reading and w
indicates that you create a new file
for writing, the two access modes are incompatible.
r
or w
as
Access ModeOne possible correction is to use the access mode corresponding to what you intend to do.
#include <stdio.h> void func(void) { FILE *file = fopen("data.txt", "w"); if(file!=NULL) { fputs("new data",file); fclose(file); } }
Incorrect data type passed to va_arg
This issue occurs when the data type in a va_arg
call does not
match the data type of the variadic function argument that va_arg
reads.
For instance, you pass an unsigned char
argument to a variadic
function func
. Because of default argument promotion, the argument is
promoted to int
. When you use a va_arg
call that
reads an unsigned char
argument, a type mismatch
occurs.
void func (int n, ...) { ... va_list args; va_arg(args, unsigned char); ... } void main(void) { unsigned char c; func(1,c); }
In a variadic
function (function with variable number of arguments), you
use va_arg
to read each argument from the
variable argument list (va_list
). The
va_arg
use does not guarantee that
there actually exists an argument to read or that the
argument data type matches the data type in the
va_arg
call. You have to make sure
that both conditions are true.
Reading an incorrect
type with a va_arg
call can result in
undefined behavior. Because function arguments reside on the
stack, you might access an unwanted area of the
stack.
Make sure that the data type of the argument passed to the variadic function
matches the data type in the va_arg
call.
Arguments of a variadic function undergo default argument promotions. The argument
data types of a variadic function cannot be determined from a prototype. The
arguments of such functions undergo default argument promotions (see Sec. 6.5.2.2
and 7.15.1.1 in the C99 Standard). Integer arguments undergo integer promotion and
arguments of type float
are promoted to
double
. For integer arguments, if a data type can be represented
by an int
, for instance, char
or
short
, it is promoted to an int
.
Otherwise, it is promoted to an unsigned int
. All other arguments
do not undergo promotion.
To avoid undefined and implementation-defined behavior, minimize the use of
variadic functions. Use the checkers for MISRA C:2012 Rule 17.1
or
MISRA
C++:2008 Rule 8-4-1
to detect use of variadic functions.
#include <stdarg.h> #include <stdio.h> unsigned char func(size_t count, ...) { va_list ap; unsigned char result = 0; va_start(ap, count); if (count > 0) { result = va_arg(ap, unsigned char); //Noncompliant } va_end(ap); return result; } void func_caller(void) { unsigned char c = 0x12; (void)func(1, c); }
In this example, func
takes an unsigned char
argument, which undergoes default argument promotion to int
. The
data type in the va_arg
call is still unsigned
char
, which does not match the int
argument
type.
int
as va_arg
ArgumentOne possible correction is to read an int
argument with
va_arg
.
#include <stdarg.h> #include <stdio.h> unsigned char func(size_t count, ...) { va_list ap; unsigned char result = 0; va_start(ap, count); if (count > 0) { result = va_arg(ap, int); } va_end(ap); return result; } void func_caller(void) { unsigned char c = 0x12; (void)func(1, c); }
Standard function call with incorrect arguments
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 Type | Situation | Risk | Fix |
---|---|---|---|
String manipulation functions such as
strlen and
strcpy | The 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
fread | The 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
| Test the return value of the
If
the return value is -1, check the value
of |
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
mkstemps | The 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
setenv | The 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 |
| Some implementations do not handle these edge cases. | Test the string for
"" before using it as
function argument. |
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:
Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface.
Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser.
Annotate Code and Hide Known or Acceptable Results if you review results in an IDE.
#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 Compiler (-compiler)
.
NULL
-terminated
StringPass 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); }
Use of automatic variable as putenv-family function argument
This issue occurs when the argument of a putenv
-family function
is a local variable with automatic duration.
The function
putenv(char *string)
inserts a
pointer to its supplied argument into the environment array,
instead of making a copy of the argument. If the argument is
an automatic variable, its memory can be overwritten after
the function containing the putenv()
call
returns. A subsequent call to getenv()
from another function returns the address of an out-of-scope
variable that cannot be dereferenced legally. This
out-of-scope variable can cause environment variables to
take on unexpected values, cause the program to stop
responding, or allow arbitrary code execution
vulnerabilities.
Use setenv()
/unsetenv()
to set and unset
environment variables. Alternatively, use putenv
-family function
arguments with dynamically allocated memory, or, if your application has no reentrancy
requirements, arguments with static duration. For example, a single thread execution with no
recursion or interrupts does not require reentrancy. It cannot be called (reentered) during
its execution.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE1024 1024 void func(int var) { char env[SIZE1024]; int retval = sprintf(env, "TEST=%s", var ? "1" : "0"); if (retval <= 0) { /* Handle error */ } /* Environment variable TEST is set using putenv(). The argument passed to putenv is an automatic variable. */ retval = putenv(env); //Noncompliant if (retval != 0) { /* Handle error */ } }
In this example, sprintf()
stores the character string
TEST=var
in env
. The value of the environment
variable TEST
is then set to var
by using
putenv()
. Because env
is an automatic variable, the
value of TEST
can change once func()
returns.
static
Variable for Argument of
putenv()
Declare env
as a static-duration variable. The memory location of
env
is not overwritten for the duration of the program, even after
func()
returns.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE1024 1024 void func(int var) { /* static duration variable */ static char env[SIZE1024]; int retval = snprintf(env,"TEST=%s", var ? "1" : "0"); if (retval <= 0) { /* Handle error */ } /* Environment variable TEST is set using putenv() */ retval=putenv(env); if (retval != 0) { /* Handle error */ } }
setenv()
to Set Environment Variable
ValueTo set the value of TEST
to var
, use
setenv()
.
#include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE1024 1024 void func(int var) { /* Environment variable TEST is set using setenv() */ int retval = setenv("TEST", var ? "1" : "0", 1); if (retval != 0) { /* Handle error */ } }
Writing to const qualified object
This issue occurs when you do one of the following:
Use a
const
-qualified object as the destination of an assignment.Pass a
const
-qualified object to a function that modifies the argument.
For instance, the defect can occur in the following situations:
You pass a
const
-qualified object as first argument of one of the following functions:mkstemp
mkostemp
mkostemps
mkdtemp
You pass a
const
-qualified object as the destination argument of one of the following functions:strcpy
strncpy
strcat
memset
You perform a write operation on a
const
-qualified object.
The risk depends
upon the modifications made to the
const
-qualified object.
Situation | Risk |
---|---|
Passing to mkstemp ,
mkostemp ,
mkostemps ,
mkdtemp , and so
on. | These functions replace the last six
characters of their first argument with a
string. Therefore, they expect a modifiable
char array as their
first argument. |
Passing to strcpy ,
strncpy ,
strcat ,
memset and so
on. | These functions modify their destination
argument. Therefore, they expect a
modifiable char array as
their destination argument. |
Writing to the object | The const qualifier
implies an agreement that the value of the
object will not be modified. By writing to a
const -qualified
object, you break the agreement. The result
of the operation is undefined. |
The fix depends on the modification made to the const
-qualified
object.
Situation | Fix |
---|---|
Passing to mkstemp ,
mkostemp , mkostemps ,
mkdtemp , and so on. | Pass a non-const object as first argument
of the function. |
Passing to strcpy ,
strncpy , strcat ,
memset and so on. | Pass a non-const object as destination
argument of the function. |
Writing to the object | Perform the write operation on a non-const
object. |
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:
Address Results in Polyspace User Interface Through Bug Fixes or Justifications if you review results in the Polyspace user interface.
Address Results in Polyspace Access Through Bug Fixes or Justifications (Polyspace Access) if you review results in a web browser.
Annotate Code and Hide Known or Acceptable Results if you review results in an IDE.
#include <string.h> const char* buffer = "abcdeXXXXXXX"; void func(char* string) { char *ptr = (char*)strchr(buffer,'X'); if(ptr) strcpy(ptr,string); //Noncompliant }
In this example, because the pointer buffer
is const
-qualified, strchr(buffer,'X')
returns a const
-qualified char*
pointer. When this char*
pointer is used as the destination argument of strcpy
, a Writing to const qualified object error appears.
const
-Qualified
Object to Non-const
ObjectOne possible correction is to assign the constant string to
a non-const
object and use the non-const
object
as destination argument of strchr
.
#include <string.h> char buffer[] = "abcdeXXXXXXX"; void func(char* string) { char *ptr = (char*)strchr(buffer,'X'); if(ptr) strcpy(ptr,string); }
Check Information
Category: Others |
Version History
Introduced in R2023b
See Also
External Websites
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)