Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

The std::basic_string type uses the traits design pattern to handle implementation details of the various string types, resulting in a series of string-like classes with a common, underlying implementation. Specifically, the std::basic_string class is paired with std::char_traits to create the std::stringstd::wstringstd::u16string, and std::u32string classes. The std::char_traits class is explicitly specialized to provide policy-based implementation details to the std::basic_string type. One such implementation detail is the std::char_traits::length() function, which is frequently used when dealing with to determine the number of characters in a null-terminated string data such as const char * or const wchar_t * values. According to the C++ Standard, [char.traits.require], Table 62 [ISO/IEC 14882-2014], passing a null pointer to this function results in is undefined behavior because it would result in dereferencing a null pointer.

The following std::basic_string member functions result in a call to std::char_traits::length():

  • basic_string::basic_string(const charT *, const Allocator &)
  • basic_string &basic_string::append(const charT *) 
  • basic_string &basic_string::assign(const charT *)
  • basic_string &basic_string::insert(size_type, const charT *)
  • basic_string &basic_string::replace(size_type, size_type, const charT *)
  • basic_string &basic_string::replace(const_iterator, const_iterator, const charT *)
  • size_type basic_string::find(const charT *, size_type)
  • size_type basic_string::rfind(const charT *, size_type)
  • size_type basic_string::find_first_of(const charT *, size_type)
  • size_type basic_string::find_last_of(const charT *, size_type)
  • size_type basic_string::find_first_not_of(const charT *, size_type)
  • size_type basic_string::find_last_not_of(const charT *, size_type)
  • int basic_string::compare(const charT *)
  • int basic_string::compare(size_type, size_type, const charT *)
  • basic_string &basic_string::operator=(const charT *)
  • basic_string &basic_string::operator+=(const charT *)

The following std::basic_string nonmember functions result in a call to to std::char_traits::length():

  • basic_string operator+(const charT *, const basic_string&)
  • basic_string operator+(const charT *, basic_string &&)
  • basic_string operator+(const basic_string &, const charT *)
  • basic_string operator+(basic_string &&, const charT *)
  • bool operator==(const charT *, const basic_string &)
  • bool operator==(const basic_string &, const charT *)
  • bool operator!=(const charT *, const basic_string &)
  • bool operator!=(const basic_string &, const charT *)
  • bool operator<(const charT *, const basic_string &)
  • bool operator<(const basic_string &, const charT *)
  • bool operator>(const charT *, const basic_string &)
  • bool operator>(const basic_string &, const charT *)
  • bool operator<=(const charT *, const basic_string &)
  • bool operator<=(const basic_string &, const charT *)
  • bool operator>=(const charT *, const basic_string &)
  • bool operator>=(const basic_string &, const charT *)

Do not call any of the above preceding functions with a null pointer as the const charT * argument.

This rule is a specific instance of EXP34-C. Do not dereference null pointers.

Implementation Details

Some standard library vendors, such as libstdc++, will throw a std::logic_error when a null pointer is used in these the above function calls, though not when calling std::char_traits::length(). However, this is std::logic_error is not a requirement from the standardof the C++ Standard, and not all vendors implement this behavior, such as some vendors (e.g., libc++ and the Microsoft Visual Studio STL) do not implement this behavior. For portability, you should not rely on this behavior.

Noncompliant Code Example

In this noncompliant code example, a std::string object is created from the results of a call to std::getenv(). However, since because std::getenv() returns a null pointer on failure, this code can lead to undefined behavior when the environment variable does not exist (or some other error occurs).

Code Block
bgColor#FFcccc
langcpp
#include <cstdlib>
#include <string>
 
void f() {
  std::string tmp(std::getenv("TMP"));
  if (!tmp.empty()) {
    // ...
  }
}

Compliant Solution

In this compliant solution, the results from the call to std::getenv() are checked for null prior to constructing before the std::string object :is constructed.

Code Block
bgColor#ccccff
langcpp
#include <cstdlib>
#include <string>
 
void f() {
  const char *tmpPtrVal = std::getenv("TMP");
  std::string tmp(tmpPtrVal ? tmpPtrVal : "");
  if (!tmp.empty()) {
    // ...
  }
}

Risk Assessment

Dereferencing a null pointer is undefined is undefined behavior, typically abnormal program termination. In some situations, however, dereferencing a null pointer can lead to the execution of arbitrary code [Jack 2007][van Sprundel 2006]. The indicated severity is for this more severe case; on platforms where it is not possible to exploit a null pointer dereference to execute arbitrary code, the actual severity is low.

Rule

Severity

Likelihood

Detectable

Remediation Cost

Repairable

Priority

Level

STR36

STR51-CPP

High

Likely

No

Medium

Yes

P18

L1

Automated Detection

Tool

Version

Checker

Description

   

Astrée

Include Page
Astrée_V
Astrée_V

assert_failure

CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.MEM.NPD

Null Pointer Dereference

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

DF4770, DF4771, DF4772, DF4773, DF4774


Klocwork
Include Page
Klocwork_V
Klocwork_V

NPD.CHECK.CALL.MIGHT
NPD.CHECK.CALL.MUST
NPD.CHECK.MIGHT
NPD.CHECK.MUST
NPD.CONST.CALL
NPD.CONST.DEREF
NPD.FUNC.CALL.MIGHT
NPD.FUNC.CALL.MUST
NPD.FUNC.MIGHT
NPD.FUNC.MUST
NPD.GEN.CALL.MIGHT
NPD.GEN.CALL.MUST
NPD.GEN.MIGHT
NPD.GEN.MUST
RNPD.CALL
RNPD.DEREF


Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_CPP-STR51-a

Avoid null pointer dereferencing

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C++: STR51-CPPChecks for string operations on null pointer (rule partially covered).
Security Reviewer - Static Reviewer

Include Page
Security Reviewer - Static Reviewer_V
Security Reviewer - Static Reviewer_V

shiftTooManyBitsFully implemented
 

Related Vulnerabilities

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

Related Guidelines

Bibliography

[ISO/IEC
14882-2014
9899:2011]
21
Subclause 7.
2
20.
1
3, "
Character Trait Requirements
Memory Management Functions"
[ISO/IEC
9899:2011
14882-2014]
Section 7

Subclause 21.

20

2.

3

1, "

Memory management functions

Character Trait Requirements"

[Jack 2007]
 

[van Sprundel 2006]
 

...



...

Image Modified Image Modified Image Modified