You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 32 Next »

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

Because 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 will not overflow, but the second read still could. The C++ Standard, [istream.extractors], paragraphs 7–9, describes the behavior of operator>>(basic_istream &, charT *), and states in part [ISO/IEC 14882-2014]:

operator>> then stores a null byte (charT()) in the next position, which may be the first position if no characters were extracted. operator>> then calls width(0).

Consequently, 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 for guarding against buffer overflows 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;
}

Noncompliant Code Example

In this noncompliant example, the unformatted input function std::basic_istream<T>::read() is used to read an unformatted character array of 32 characters from the given file. However, the read() function does not guarantee that the string will be null terminated, so the subsequent call of the std::string constructor results in undefined behavior if the character array does not contain a null terminator.

#include <fstream>
#include <string>
 
void f(std::istream &in) {
  char buffer[32];
  try {
    in.read(buffer, 32);
  } catch (std::ios_base::failure &E) {
    // Handle error
  }
 
  std::string str(buffer);
  // ...
}

Compliant Solution

This compliant solution continues to assume that the input from the file is exactly 32 characters, and instead of inserting a null terminator, it constructs the std::string object based on the size. If the size of the input is uncertain, it is better to use std::basic_istream<T>::readsome() or a formatted input function, depending on need.

#include <fstream>
#include <string>

void f(std::istream &in) {
  char buffer[32];
  try {
    in.read(buffer, 32);
  } catch (std::ios_base::failure &E) {
    // Handle error
  }
  std::string str(buffer, 32);
  // ...
}

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

STR50-CPP

High

Likely

Medium

P18

L1

Automated Detection

Tool

Version

Checker

Description

Parasoft C/C++test9.5BD-PB-OVERFWR, SECURITY-12 

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Related Guidelines

Bibliography

[ISO/IEC 14882-2014]

Subclause 27.7.2.2.3, "basic_istream::operator>>"
Subclause 27.7.2.3, "Unformatted Input Functions" 

[Seacord 2013b]Chapter 2, "Strings"

 


  • No labels