Versions Compared

Key

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

...

The Library Working Group, responsible for the wording of the Standard Library section of the C++ Standard, has an unresolved issue on the definition of "user-defined type." While the Library Working Group has no official stance on the definition [INCITS 2014], we define it to be any classstructunion, or enum that is not defined within namespace std or a namespace contained within namespace std. Effectively, it is a user-provided type instead of a standard library-provided type.

Noncompliant Code Example

In this noncompliant code example, the declaration of x is added to the namespace std, resulting in undefined behavior:

Code Block
bgColor#FFCCCC
langcpp
namespace std {
  int x;
}

Compliant Solution

This compliant solution assumes the intention of the programmer was to place the declaration of x into a namespace to prevent collisions with other global identifiers. Instead of placing the declaration into the namespace std, the declaration is placed into a namespace without a reserved name.

Code Block
bgColor#ccccff
langcpp
namespace nonstd {
  int x;
}

Noncompliant Code Example

In this noncompliant code example, a template specialization of std::plus is added to the namespace std in an attempt to allow std::plus to concatenate a std::string and MyString object together. However, because the template specialization is of a standard library-provided type (std::string), this results in undefined behavior.

Code Block
bgColor#FFCCCC
langcpp
#include <functional>
#include <iostream>
#include <string>

class MyString {
  std::string Data;
  
public:
  MyString(const std::string &Data) : Data(Data) {}
  
  const std::string &data() const { return Data; }
};

namespace std {
template <>
struct plus<string> : binary_function<string, MyString, string> {
  string operator()(const string &LHS, const MyString &RHS) const {
    return LHS + RHS.data();
  }
};
}

void f() {
  std::string S1("My String");
  MyString S2(" + Your String");
  std::plus<std::string> P;
  
  std::cout << P(S1, S2) << std::endl;
}

Compliant Solution

The interface for std::plus requires that both arguments to the function call operator are of the same type. Because the attempted specialization in the noncompliant code example results in undefined behavior, this compliant solution defines a new std::binary_function derivative which is capable of adding a std::string to a MyString object, without requiring modification of the namespace std.

Code Block
bgColor#ccccff
langcpp
#include <iostream>
#include <string>

class MyString {
  std::string Data;
  
public:
  MyString(const std::string &Data) : Data(Data) {}
  
  const std::string &data() const { return Data; }
};

struct my_plus : std::binary_function<std::string, MyString, std::string> {
  std::string operator()(const std::string &LHS, const MyString &RHS) const {
    return LHS + RHS.data();
  }
};

void f() {
  std::string S1("My String");
  MyString S2(" + Your String");
  my_plus P;
  
  std::cout << P(S1, S2) << std::endl;
}

Risk Assessment

Altering the standard namespace can cause undefined behavior in the C++ standard library.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC34-CPP

High

Unlikely

Medium

P6

L2

Automated Detection

Tool

Version

Checker

Description

 PRQA QA-C++

 
Include Page
PRQA QA-C++_V
PRQA QA-C++_V

-q & Name Check

 

Related Vulnerabilities

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

Related Guidelines

 

 

Bibliography

[ISO/IEC 14882-2014]17.6.4.2.1, "Namespace std"
17.6.4.2.2, "Namespace posix
[INCITS 2014]Issue 2139, "What is a User-Defined Type?"

...