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