Namespaces introduce new declarative regions for declarations, reducing the likelihood of conflicting identifiers with other declarative regions. One feature of namespaces is that they can be further extended, even within separate translation units. For instance, the following declarations are well-formed:
Code Block |
---|
namespace MyNamespace {
int I;
}
namespace MyNamespace {
int J;
}
void f() {
MyNamespace::I = MyNamespace::J = 12;
} |
The standard library introduces the namespace std
for standards-provided declarations such as std::string
, std::vector
, and std::for_each
. However, it is undefined behavior to introduce new declarations in namespace std
, except under special circumstances. The C++ Standard, [namespace.std], paragraph 1 & 2, state [ISO/IEC 14882-2014]:
1 The behavior of a C++ program is undefined if it adds
C++ places all standard definitions inside the std
namespace. Furthermore, C++ 2003, Section 17.4.3.1 "Reserved names", says:
It is undefined for a C++ program to add declarations or definitions to namespace
std
or namespaces or to a namespace within namespacestd
unless unless otherwise specified. A program may add a template specializations for specialization for any standard library template to namespacestd
. Such a specialization (complete or partial) of a standard library template results in undefined behavior unless the declaration only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited.2 The behavior of a C++ program is undefined if it declares
— an explicit specialization of any member function of a standard library class template, or
— an explicit specialization of any member function template of a standard library class or class template, or
— an explicit or partial specialization of any member class template of a standard library class or class template.
In addition to restricting extensions to the the namespace std
, the C++ Standard, [namespace.posix], paragraph 1, further states:
The behavior of a C++ program is undefined if it adds declarations or definitions to namespace
posix
or to a namespace within namespaceposix
unless otherwise specified. The namespaceposix
is reserved for use by ISO/IEC 9945 and other POSIX standards.
Do not add declarations or definitions to the standard namespaces std
or posix
, or a namespace contained therein, except for a template specialization that depends on a user-defined type
...
that meets the standard library requirements for the original template.
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 [CITATION NEEDED, link in text], we define it to be any class
, struct
, union
, 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
This code is noncompliant because it alters the standard namespace.In this noncompliant code example, the declaration of x
is added to the namespace std
, resulting in undefined behavior:
Code Block | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
#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 | ||||
---|---|---|---|---|
| ||||
#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 | highHigh | unlikelyUnlikely | mediumMedium | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
| -q & Name Check |
Related Vulnerabilities
Search for other vulnerabilities resulting resulting from the violation of this rule on the the CERT website.
Related Guidelines
|
Bibliography
...
14882-2014] | 17.6.4.2.1, "Namespace std "17.6.4.2.2, "Namespace posix " |
[???] | Issue 2139, "What is a User-Defined Type?" |
...