CWE Rule 628
Description
Rule Description
The product calls a function, procedure, or routine with arguments that are not correctly specified, leading to always-incorrect behavior and resultant weaknesses.
Polyspace Implementation
The rule checker checks for these issues:
Bad file access mode or status
Copy of overlapping memory
Invalid va_list argument
Modification of internal buffer returned from non-reentrant standard function
Standard function call with incorrect arguments
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); } }
Copy of overlapping memory
This issue occurs
when there is a memory overlap between the source and destination
argument of a copy function such as memcpy
or strcpy
.
For instance, the source and destination arguments of strcpy
are
pointers to different elements in the same string.
If there is memory overlap between the source and destination arguments of copy functions, according to C standards, the behavior is undefined.
Determine if the memory overlap is what you want. If so, find an alternative function. For instance:
If you are using
memcpy
to copy values from one memory location to another, usememmove
instead ofmemcpy
.If you are using
strcpy
to copy one string to another, usememmove
instead ofstrcpy
, as follows:s = strlen(source); memmove(destination, source, s + 1);
strlen
determines the string length without the null terminator. Therefore, you must moves+1
bytes instead ofs
bytes.
#include <string.h> char str[] = {"ABCDEFGH"}; void my_copy() { strcpy(&str[0],(const char*)&str[2]); //Noncompliant }
In this example, because the source and destination argument
are pointers to the same string str
, there is memory
overlap between their allowed buffers.
Invalid va_list argument
This issue occurs
when you use a va_list
variable as an argument
to a function in the vprintf
group but:
You do not initialize the variable previously using
va_start
orva_copy
.You invalidate the variable previously using
va_end
and do not reinitialize it.
For instance, you call the function vsprintf
as vsprintf
(buffer,format, args)
. However, before the function call,
you do not initialize the va_list
variable args
using
either of the following:
va_start(args, paramName)
.paramName
is the last named argument of a variable-argument function. For instance, for the function definitionvoid func(int n, char c, ...) {}
,c
is the last named argument.va_copy(args, anotherList)
.anotherList
is another validva_list
variable.
The behavior of an uninitialized va_list
argument
is undefined. Calling a function with an uninitialized va_list
argument
can cause stack overflows.
Before using a va_list
variable as function
argument, initialize it with va_start
or va_copy
.
Clean up the variable using va_end
only after
all uses of the variable.
#include <stdarg.h> #include <stdio.h> int call_vfprintf(int line, const char *format, ...) { va_list ap; int r=0; va_start(ap, format); r = vfprintf(stderr, format, ap); va_end(ap); r += vfprintf(stderr, format, ap); //Noncompliant return r; }
In this example, the va_list
variable ap
is
used in the vfprintf
function, after the va_end
macro
is called.
va_end
After Using va_list
VariableOne possible correction is to call va_end
only
after all uses of the va_list
variable.
#include <stdarg.h> #include <stdio.h> int call_vfprintf(int line, const char *format, ...) { va_list ap; int r=0; va_start(ap, format); r = vfprintf(stderr, format, ap); r += vfprintf(stderr, format, ap); va_end(ap); return r; }
Modification of internal buffer returned from non-reentrant standard function
This issue occurs when the following happens:
A nonreentrant standard function returns a pointer.
You attempt to write to the memory location that the pointer points to.
Nonreentrant standard functions that return a non const
-qualified
pointer to an internal buffer include getenv
,
getlogin
, crypt
, setlocale
,
localeconv
, strerror
and others.
Modifying the internal buffer that a nonreentrant standard function returns can cause the following issues:
It is possible that the modification does not succeed or alters other internal data.
For instance,
getenv
returns a pointer to an environment variable value. If you modify this value, you alter the environment of the process and corrupt other internal data.Even if the modification succeeds, it is possible that a subsequent call to the same standard function does not return your modified value.
For instance, you modify the environment variable value that
getenv
returns. If another process, thread, or signal handler callssetenv
, the modified value is overwritten. Therefore, a subsequent call togetenv
does not return your modified value.
Avoid modifying the internal buffer using the pointer returned from the function.
#include <stdlib.h> #include <string.h> void printstr(const char*); void func() { char* env = getenv("LANGUAGE"); if (env != NULL) { strncpy(env, "C", 1); //Noncompliant printstr(env); } }
In this example, the first argument of strncpy
is
the return value from a nonreentrant standard function getenv
.
The behavior can be undefined because strncpy
modifies
this argument.
getenv
and
Modify CopyOne possible solution is to copy the return value of getenv
and
pass the copy to the strncpy
function.
#include <stdlib.h> #include <string.h> enum { SIZE20 = 20 }; void printstr(const char*); void func() { char* env = getenv("LANGUAGE"); if (env != NULL) { char env_cp[SIZE20]; strncpy(env_cp, env, SIZE20); strncpy(env_cp, "C", 1); printstr(env_cp); } }
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); }
Check Information
Category: Bad Coding Practices |
Version History
Introduced in R2024a
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 (한국어)