CWE Rule 170
Description
Rule Description
The software does not terminate or incorrectly terminates a string or array with a null character or equivalent terminator.
Polyspace Implementation
The rule checker checks for these issues:
Invalid use of standard library string routine
Missing null in string array
Misuse of readlink()
Tainted NULL or non-null-terminated string
Examples
Invalid use of standard library string routine
This issue occurs when a string library function is called with invalid arguments.
The risk depends on the type of invalid arguments. For instance, using the
strcpy
function with a source argument larger than the
destination argument can result in buffer overflows.
The fix depends on the standard library function involved in the defect. In some cases, you can constrain the function arguments before the function call. For instance, if the strcpy
function:
char * strcpy(char * destination, const char* source)
strcpy
. In some cases, you can use an alternative function to avoid the error. For instance, instead of strcpy
, you can use strncpy
to control the number of bytes copied.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> #include <stdio.h> char* Copy_String(void) { char *res; char gbuffer[5],text[20]="ABCDEFGHIJKL"; res=strcpy(gbuffer,text); //Noncompliant /* Error: Size of text is less than gbuffer */ return(res); }
The string text
is larger
in size than gbuffer
. Therefore, the function strcpy
cannot
copy text
into gbuffer
.
One possible correction is to declare the destination
string gbuffer
with equal or larger size than the
source string text
.
#include <string.h> #include <stdio.h> char* Copy_String(void) { char *res; /*Fix: gbuffer has equal or larger size than text */ char gbuffer[20],text[20]="ABCDEFGHIJKL"; res=strcpy(gbuffer,text); return(res); }
Missing null in string array
This issue occurs when a string does not have enough
space to terminate with a null character '\0'
.
This defect applies only for projects in C.
A buffer overflow can occur if you copy a string to an array without assuming the implicit null terminator.
If you initialize a character array with a literal, avoid specifying the array bounds.
char three[] = "THREE";
If the issue occurs after initialization, you might have to increase the size of the array by one to account for the null terminator.
In certain circumstances, you might want to initialize the character array with a sequence of characters instead of a string. In this situation, 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.
void countdown(int i) { static char one[5] = "ONE"; static char two[5] = "TWO"; static char three[5] = "THREE"; //Noncompliant }
The character array three
has a size of 5 and 5 characters 'T'
, 'H'
, 'R'
, 'E'
, and 'E'
. There is no room for the null character at the end because three
is only five bytes large.
One possible correction is to change the array size to allow for the five characters plus a null character.
void countdown(int i) { static char one[5] = "ONE"; static char two[5] = "TWO"; static char three[6] = "THREE"; }
One possible correction is to initialize the string by leaving the array size blank. This initialization method allocates enough memory for the five characters and a terminating-null character.
void countdown(int i) { static char one[5] = "ONE"; static char two[5] = "TWO"; static char three[] = "THREE"; }
Misuse of readlink()
This issue occurs
when you pass a buffer size argument to readlink()
that
does not leave space for a null terminator in the buffer.
For instance:
ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf));
readlink()
does not leave space to enter a null terminator.The readlink()
function copies the content
of a symbolic link (first argument) to a buffer (second argument).
However, the function does not append a null terminator to the copied
content. After using readlink()
, you must explicitly
add a null terminator to the buffer.
If you fill the entire buffer when using readlink
,
you do not leave space for this null terminator.
When using the readlink()
function, make
sure that the third argument is one less than the buffer size.
Then, append a null terminator to the buffer. To determine where
to add the null terminator, check the return value of readlink()
.
If the return value is -1, an error has occurred. Otherwise, the return
value is the number of characters (bytes) copied.
#include <unistd.h> #define SIZE1024 1024 extern void display_path(const char *); void func() { char buf[SIZE1024]; ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf)); //Noncompliant if (len > 0) { buf[len - 1] = '\0'; } display_path(buf); }
In this example, the third argument of readlink
is
exactly the size of the buffer (second argument). If the first argument
is long enough, this use of readlink
does not leave
space for the null terminator.
Also, if no
characters are copied, the return value of readlink
is
0. The following statement leads to a buffer underflow when len
is
0.
buf[len - 1] = '\0';
One possible correction is to make sure that the third argument
of readlink
is one less than size of the second
argument.
The following corrected code also accounts for readlink
returning
0.
#include <stdlib.h> #include <unistd.h> #define fatal_error() abort() #define SIZE1024 1024 extern void display_path(const char *); void func() { char buf[SIZE1024]; ssize_t len = readlink("/usr/bin/perl", buf, sizeof(buf) - 1); if (len != -1) { buf[len] = '\0'; display_path(buf); } else { /* Handle error */ fatal_error(); } }
Tainted NULL or non-null-terminated string
This issue occurs when strings from unsecure sources are used in string manipulation routines
that implicitly dereference the string buffer, for instance, strcpy
or
sprintf
.
Tainted NULL or non-null-terminated string raises no
defect for a string returned from a call to scanf
-family variadic
functions. Similarly, no defect is raised when you pass the string with a
%s
specifier to printf
-family variadic
functions.
If a string is from an unsecure source, it is possible that an attacker manipulated the string or pointed the string pointer to a different memory location.
If the string is NULL, the string routine cannot dereference the string, causing the program to crash. If the string is not null-terminated, the string routine might not know when the string ends. This error can cause you to write out of bounds, causing a buffer overflow.
Validate the string before you use it. Check that:
The string is not NULL.
The string is null-terminated
The size of the string matches the expected size.
By default, Polyspace® assumes that data from external sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider any data
that does not originate in the current scope of Polyspace analysis as tainted, use the
command line option -consider-analysis-perimeter-as-trust-boundary
.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define SIZE128 128 #define MAX 40 extern void print_str(const char*); void warningMsg(void) { char userstr[MAX]; read(0,userstr,MAX); char str[SIZE128] = "Warning: "; strncat(str, userstr, SIZE128-(strlen(str)+1));//Noncompliant //Noncompliant print_str(str); }
In this example, the string str
is concatenated
with the argument userstr
. The value of userstr
is
unknown. If the size of userstr
is greater than
the space available, the concatenation overflows.
One possible correction is to check the size of userstr
and
make sure that the string is null-terminated before using it in strncat
.
This example uses a helper function, sansitize_str
,
to validate the string. The defects are concentrated in this function.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define SIZE128 128 #define MAX 40 extern void print_str(const char*); int sanitize_str(char* s) { int res = 0; if (s && (strlen(s) > 0)) { // Noncompliant-TAINTED_STRING only flagged here //Noncompliant // - string is not null // - string has a positive and limited size // - TAINTED_STRING on strlen used as a firewall res = 1; } return res; } void warningMsg(void) { char userstr[MAX]; read(0,userstr,MAX); char str[SIZE128] = "Warning: "; if (sanitize_str(userstr)) strncat(str, userstr, SIZE128-(strlen(str)+1)); print_str(str); }
Another possible correction is to call function errorMsg
and
warningMsg
with specific strings.
#include <stdio.h> #include <string.h> #include <stdlib.h> #define SIZE128 128 extern void print_str(const char*); void warningMsg(char* userstr) { char str[SIZE128] = "Warning: "; strncat(str, userstr, SIZE128-(strlen(str)+1)); print_str(str); } void errorMsg(char* userstr) { char str[SIZE128] = "Error: "; strncat(str, userstr, SIZE128-(strlen(str)+1)); print_str(str); } int manageSensorValue(int sensorValue) { int ret = sensorValue; if ( sensorValue < 0 ) { errorMsg("sensor value should be positive"); exit(1); } else if ( sensorValue > 50 ) { warningMsg("sensor value greater than 50 (applying threshold)..."); sensorValue = 50; } return sensorValue; }
Check Information
Category: Data Neutralization Issues |
Version History
Introduced in R2023a
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 (한국어)