Copying data to a buffer that is not large enough to hold that data results in a buffer overflow. Buffer overflows occur frequently when manipulating strings [Seacord 2013b]. To prevent such errors, either limit copies through truncation or, preferably, ensure that the destination is of sufficient size to hold the character data to be copied and the null-termination character. This rule is a C++-specific instance of STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator.
Noncompliant Code Example
Since the input is unbounded, the following code could lead to a buffer overflow:
#include <iostream>
void f() {
char buf[12];
std::cin >> buf;
}
Noncompliant Code Example
To solve this problem, it may be tempting to use the std::ios_base::width() method, but there still is a trap as shown in this noncompliant code example. In this example, the first read won't overflow, but the second still could. The C++ Standard, [istream.extractors], paragraphs 7-9 describe the behavior of operator>>(basic_istream &, charT *), and states in part:
operator>>then stores a null byte (charT()) in the next position, which may be the first position if no characters were extracted.operator>>then callswidth(0).
Thus, it is necessary to call width() prior to each operator>> call passing a bounded array.
#include <iostream>
void f() {
char buf_one[12];
char buf_two[12];
std::cin.width(12);
std::cin >> buf_one;
std::cin >> buf_two;
}
Noncompliant Code Example
The following noncompliant code example calls std::ios_base_width() prior to each call to operator>>(). However, it still does not account for the input being truncated. Only the first 11 characters are read from the standard input stream, and a null terminator is then appended. The input could therefore be truncated, leading to information loss or a possible vulnerability.
#include <iostream>
void f() {
char buf_one[12];
char buf_two[12];
std::cin.width(12);
std::cin >> buf_one;
std::cin.width(12);
std::cin >> buf_two;
}
Compliant Solution
The best solution for ensuring that data is not truncated, and buffer overflows are guarded against, is to use std::string instead of a bounded array, as in this compliant solution:
#include <iostream>
#include <string>
void f() {
std::string input;
std::string string_one, string_two;
std::cin >> string_one >> string_two;
}
Risk Assessment
Copying string data to a buffer that is too small to hold that data results in a buffer overflow. Attackers can exploit this condition to execute arbitrary code with the permissions of the vulnerable process.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
STR35-CPP | High | Likely | Medium | P18 | L1 |
Automated Detection
Tool | Version | Checker | Description |
|---|---|---|---|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
| CERT C Secure Coding Standard | STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator |
Bibliography
| [ISO/IEC 14882-2014] | 27.7.2.2.3, " |
| [Seacord 2013b] | Chapter 2, "Strings" |
007. Characters and Strings (STR) STR08-CPP. Do not specify the bound of a character array initialized with a string literal