CERT C++: STR50-CPP
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.
Buffer overflow from incorrect string format specifier.
Destination buffer overflow in string manipulation.
Insufficient destination buffer size.
Input string not null-terminated
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 |
std::cin::operator>> and
std::wcin::operator>> | Inherently dangerous — You cannot control the length of input from the console. | Preface calls to To avoid potential buffer overflow and truncated input, use
|
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; }
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 <cstring> int main(int argc, char *argv[]) { const char *const source = (argc && argv[0]) ? argv[0] : ""; char destination[128]; strcpy(const_cast<char*>(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 <cstring> #include <cstdlib> 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(const_cast<char*>(source), destination);//Compliant }else{ /*Handle Error*/ } //... free(destination); return 0; }
Input string not null-terminated
The issue Input string not null-terminated occurs when both of these conditions are true:
You obtain a string from an input function that does not necessarily terminates the string by a null character.
You use the input string that does not have the terminating null character in places where a null-terminated string is expected.
For instance:
char str[10]; scanf("%10c", str); std::string S(str);//Null-terminated string expected
std::string
expects a string terminated by a null
character, but str
is not null-terminated. Polyspace reports a violation of this rule.Functions in the C++ library assume that a valid string is terminated by a null character and apply this assumption string algorithms. Using these functions and algorithms with a string that lacks a terminating null character results in undefined behavior.
The fix for this issue depends on the context:
You can fix this issue by terminating raw input strings by a null. For example, this code declares
str
with 11 elements. After filling the first 10 elements with the raw input, assign the last element the value'\0'
. After manually terminating the input string with a null character, you can use the input string with standard template library (STL) string functions without violating this rule.char str[11]; scanf("%10c", str); str[10] = '\0'; std::string S(str);//Valid string
Some C++ functions accepts character pointers or substrings as input. These functions can correctly handle a raw character array without a terminating null character. For instance, This code constructs the
std::string
objectS
by using a nondefault constructor. This constructor allows the use ofstr
, which lacks a terminating null character. Such uses do not violate this rule.char str[10]; scanf("%10c", str); std::string S(str,sizeof(str));//Valid use of substring
In this example, the read
function accepts an array of characters,
which is then stored in the char
array buffer
.
Because buffer
does not have a terminating null character, using
buffer
with the function printf()
results in
undefined behavior. Polyspace reports a violation of this rule.
#include <iostream> #include <string> #include <fstream> #include <cstdio> void echo_instream(std::istream& instream) { //... char buffer[10]; instream.read(buffer,sizeof(buffer)); //... printf("%s", buffer); //Noncompliant //... }
'\0'
To fix this issue, manually add the terminating null character at the end of
buffer
.
#include <iostream> #include <string> #include <fstream> #include <cstdio> void echo_instream(std::istream& instream) { //... char buffer[10]; instream.read(buffer,sizeof(buffer)-1); buffer[9] = '\0'; //... printf("%s", buffer); //Compliant //... }
Check Information
Group: 05. Characters and Strings (STR) |
Version History
Introduced in R2019aR2023a: Checker detects non-null-terminated character arrays passed in place of std::string
arguments
The rule checker reports a violation of this rule if you use an input string that is not null-terminated instead of a null terminated string. For example, in this code, the constructor of the std::string
object expects a null-terminated string. Instead, the code uses the input string buffer, which is not null-terminated, and the rule checker reports a violation.
void foo(std::istream& instream) { //... char buffer[10]; instream.read(buffer,sizeof(buffer)); //... std::string str(buffer); //... }
R2022b: 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.
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 (한국어)