CERT C: Rule STR31-C
Guarantee that storage for strings has sufficient space for character data and the null terminator
Description
Rule Definition
Guarantee that storage for strings has sufficient space for character data and the null terminator.1
Polyspace Implementation
The rule checker checks for these issues:
Use of dangerous standard function.
Missing null in string array.
Buffer overflow from incorrect string format specifier.
Destination buffer overflow in string manipulation.
Insufficient destination buffer size.
Examples
Use of dangerous standard function
The Use of dangerous standard function check highlights uses of functions that are inherently dangerous or potentially dangerous given certain circumstances. The following table lists possibly dangerous functions, the risks of using each function, and what function to use instead.
Dangerous Function | Risk Level | Safer Function |
---|---|---|
gets | Inherently dangerous — You cannot control the length of input from the console. | fgets |
cin | Inherently dangerous — You cannot control the length of input from the console. | Avoid or prefaces calls to cin with cin.width . |
strcpy | Possibly dangerous — If the source length is greater than the destination, buffer overflow can occur. | strncpy |
stpcpy | Possibly dangerous — If the source length is greater than the destination, buffer overflow can occur. | stpncpy |
lstrcpy or StrCpy | Possibly dangerous — If the source length is greater than the destination, buffer overflow can occur. | StringCbCopy , StringCchCopy , strncpy , strcpy_s ,
or strlcpy |
strcat | Possibly dangerous — If the concatenated result is greater than the destination, buffer overflow can occur. | strncat , strlcat , or strcat_s |
lstrcat or StrCat | Possibly dangerous — If the concatenated result is greater than the destination, buffer overflow can occur. | StringCbCat , StringCchCat , strncay , strcat_s ,
or strlcat |
wcpcpy | Possibly dangerous — If the source length is greater than the destination, buffer overflow can occur. | wcpncpy |
wcscat | Possibly dangerous — If the concatenated result is greater than the destination, buffer overflow can occur. | wcsncat , wcslcat , or wcncat_s |
wcscpy | Possibly dangerous — If the source length is greater than the destination, buffer overflow can occur. | wcsncpy |
sprintf | Possibly dangerous — If the output length depends on unknown lengths or values, buffer overflow can occur. | snprintf |
vsprintf | Possibly dangerous — If the output length depends on unknown lengths or values, buffer overflow can occur. | vsnprintf |
These functions can cause buffer overflow, which attackers can use to infiltrate your program.
The fix depends on the root cause of the defect. Often the result details show a sequence of events that led to the defect. You can implement the fix on any event in the sequence. If the result details do not show the event history, you can trace back using right-click options in the source code and see previous related events. See also Interpret Bug Finder Results in Polyspace Desktop User Interface.
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.
sprintf
#include <stdio.h> #include <string.h> #include <iostream> #define BUFF_SIZE 128 int dangerous_func(char *str) { char dst[BUFF_SIZE]; int r = 0; if (sprintf(dst, "%s", str) == 1) //Noncompliant { r += 1; dst[BUFF_SIZE-1] = '\0'; } return r; }
This example function uses sprintf
to copy
the string str
to dst
. However,
if str
is larger than the buffer, sprintf
can
cause buffer overflow.
snprintf
with Buffer
SizeOne possible correction is to use snprintf
instead
and specify a buffer size.
#include <stdio.h> #include <string.h> #include <iostream> #define BUFF_SIZE 128 int dangerous_func(char *str) { char dst[BUFF_SIZE]; int r = 0; if (snprintf(dst, sizeof(dst), "%s", str) == 1) { r += 1; dst[BUFF_SIZE-1] = '\0'; } return r; }
Missing null in string array
Missing null in string array 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"; }
Buffer overflow from incorrect string format specifier
Buffer overflow from incorrect string
format specifier occurs when the format specifier argument
for functions such as sscanf
leads to an overflow
or underflow in the memory buffer argument.
If the format specifier specifies a precision that is greater than the memory buffer size, an overflow occurs. Overflows can cause unexpected behavior such as memory corruption.
Use a format specifier that is compatible with the memory buffer size.
#include <stdio.h> void func (char *str[]) { char buf[32]; sscanf(str[1], "%33c", buf); //Noncompliant }
In this example, buf
can contain 32 char
elements.
Therefore, the format specifier %33c
causes a buffer
overflow.
One possible correction is to use a smaller precision in the format specifier.
#include <stdio.h> void func (char *str[]) { char buf[32]; sscanf(str[1], "%32c", buf); }
Destination buffer overflow in string manipulation
Destination buffer overflow in string manipulation occurs when certain string manipulation functions write to their destination buffer argument at an offset greater than the buffer size.
For instance, when calling the function sprintf(char*
buffer, const char* format)
, you use a constant string format
of
greater size than buffer
.
Buffer overflow can cause unexpected behavior such as memory corruption or stopping your system. Buffer overflow also introduces the risk of code injection.
One possible solution is to use alternative functions to constrain the number of characters written. For instance:
If you use
sprintf
to write formatted data to a string, usesnprintf
,_snprintf
orsprintf_s
instead to enforce length control. Alternatively, useasprintf
to automatically allocate the memory required for the destination buffer.If you use
vsprintf
to write formatted data from a variable argument list to a string, usevsnprintf
orvsprintf_s
instead to enforce length control.If you use
wcscpy
to copy a wide string, usewcsncpy
,wcslcpy
, orwcscpy_s
instead to enforce length control.
Another possible solution is to increase the buffer size.
sprintf
Use#include <stdio.h> void func(void) { char buffer[20]; char *fmt_string = "This is a very long string, it does not fit in the buffer"; sprintf(buffer, fmt_string); //Noncompliant }
In this example, buffer
can contain 20 char
elements
but fmt_string
has a greater size.
snprintf
Instead
of sprintf
One possible correction is to use the snprintf
function
to enforce length control.
#include <stdio.h> void func(void) { char buffer[20]; char *fmt_string = "This is a very long string, it does not fit in the buffer"; snprintf(buffer, 20, fmt_string); }
Insufficient destination buffer size
Insufficient destination buffer size occurs when the destination buffer in a strcpy
operation cannot accommodate the source buffer and a null terminator. This issue is reported if the size of the source buffer is unknown. Consider this code:
int main (int argc, char *argv[]) { const char *const input = ((argc && argv[0]) ? argv[0] : ""); char str[100]; strcpy(input, str); // Noncompliant }
input
is unknown. The size of the destination buffer str
might be smaller than the value (strlen(input)+1)
. Polyspace® reports a violation on the strcpy
operation.Using a destination buffer of insufficient size might allow an attacker to cause a buffer overflow. In the preceding code example, if argv[0]
contains 100 or more characters, the strcpy
operation results in a buffer overflow.
Before calling the function strcpy()
, allocate sufficient memory dynamically. For instance, use the function strlen()
to determine the size of the source buffer and then allocate the destination buffer so that its size is greater than the value strlen(source) + 1
.
In this example, the size of the source
buffer is unknown, while the size of the destination
buffer is fixed at 128
. The size of the destination
buffer might not be sufficient to accommodate the characters from the source
buffer and terminate the buffer with a null. Polyspace reports a violation of the rule.
#include <string.h> int main(int argc, char *argv[]) { const char *const source = (argc && argv[0]) ? argv[0] : ""; char destination[128]; strcpy(source, destination);//Noncompliant return 0; }
This violation is resolved by allocating sufficient memory for the destination
buffer. For instance, use the function strlen()
to calculate the size of the source
buffer and allocate sufficient memory for the destination
buffer so that it can accommodate all characters from the source
buffer and the null terminator ('\0'
).
#include <string.h> int main(int argc, char *argv[]) { const char *const source = (argc && argv[0]) ? argv[0] : ""; char* destination = (char *)malloc(strlen(source)+ 1); if(destination!=NULL){ strcpy(source, destination);//Compliant }else{ /*Handle Error*/ } //... free(destination); return 0; }
Check Information
Group: Rule 07. Characters and Strings (STR) |
Version History
Introduced in R2019aR2022b: Checker flags insufficient destination buffer size in strcpy()
operation
The rule checker reports a violation of this rule if the size of a destination buffer in a strcpy()
operation is insufficient to accommodate the source buffer and a null terminator.
See Also
External Websites
1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.
ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.
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 (한국어)