Secure Coding in C++11 and C++14
Writing secure C++ code is hard. C++11 and C++14 have added new facilities that change the way programmers write C++ code with the introduction of features like lambdas and concurrency. Few resources exist, however, describing how these new facilities also increase the number of ways in which security vulnerabilities can be introduced into a program or how to avoid using these facilities insecurely. Previous secure coding efforts, including the SEI CERT C Coding Standard and SEI CERT Oracle Coding Standard for Java , have proved successful in helping programmers identify possible insecure code in C and Java but do not provide sufficient information to cover C++. Other efforts, such as MISRA C++:2008 and the community-led C++ Core Guidelines, create a subset of the C++ language and do not focus on security. This blog post introduces the SEI CERT C++ Coding Standard and explores some examples of areas in C++ that can result in security vulnerabilities.
The SEI CERT C++ Coding Standard
The SEI CERT C++ Coding Standard provides rules for secure coding in the C++ programming language. The goal of these rules is to develop safe, reliable, and secure systems, for example, by eliminating undefined behaviors that can lead to exploitable vulnerabilities. Conformance to the coding rules defined in this standard is necessary (although insufficient) to ensure the safety, reliability, and security of software systems developed in C++. The application of this coding standard will result in high-quality systems that are reliable, robust, and resistant to attack. The complete set of rules can be found on the CERT Secure Coding Wiki where these rules are being actively developed and maintained.
The CERT C++ Coding Standard comprises more than 80 rules in the following 11 chapters:
- Declarations and Initialization (DCL) concerns issues that deal with declarations or initialization, such as C-style variadic functions, defining unnamed namespaces in header files, and initialization cycles for objects with static storage duration.
- Expressions (EXP) concerns issues pertaining to expressions, such as reading uninitialized memory or relying on the value of a moved-from object.
- Integers (INT) concerns issues pertaining to unsafe integer operations, such as casting to enumerations.
- Containers (CTR) concerns issues dealing with containers, such as arrays and std::vector.
- Characters and Strings (STR) concerns issues dealing with strings, such as attempting to create a std::string from a null pointer.
- Memory Management (MEM) concerns issues pertaining to memory allocation and deallocation, such as accessing freed memory, and avoiding the use of the default operator new implementation for over-aligned types.
- Input Output (FIO) concerns issues pertaining to the file system, such as the need to have an intervening positioning call between input and output operations on a file stream.
- Exceptions and Error Handling (ERR) concerns issues dealing with exceptions and error handling, such as why you should avoid using
longjmp(), and why exception objects need to be nothrow copy constructible.
- Object Oriented Programming (OBJ) concerns issues related to object-oriented programming, such as gracefully handling self-assignment and how copy operations must not mutate the source of the copy.
- Concurrency (CON) concerns issues dealing with concurrency and multithreading, such as how to avoid deadlock by locking in a predefined order.
- Miscellaneous (MSC) concerns issues that do not relate to other categories, such as the One Definition Rule and the requirement for signal handlers to be a plain old function.
The Close Relationship Between C and C++
Due to the close relationship between C and C++, many of the rules and recommendations in the CERT C Coding Standard are also applicable to C++. . Accordingly, each of the chapters outlined above lists the related C rules that also apply in C++. For instance, EXP34-C. Do not dereference null pointers applies to both C and C++ because both languages specify that dereferencing a null pointer is undefined behavior, which will lead to a security vulnerability in either language.
Any CERT C Coding Standard rule that does not apply to the CERT C++ Coding Standard is marked with a "not-for-cpp" label. Sometimes this marking occurs because the rule does not apply in C++ at all. For instance, DCL38-C. Use the correct syntax when declaring a flexible array member does not apply to C++ because C++ does not have the notion of flexible array members. Other times, a dedicated C++ rule has been crafted on the subject and so the C rule is superseded; as is the case with EXP50-CPP. Do not depend on the order of evaluation for side effects.
Finally, there are numerous rules that only apply to C++ and not to C, such as EXP61-CPP. A lambda object must not outlive any of its reference captured objects, which focuses on scenarios where functions return a lambda object that has captured a local variable by reference (leading to accessing a dangling reference when the lambda is executed). The CERT C++ Coding Standard is intended to be a companion to the CERT C Coding Standard rather than a replacement.
Each guideline consists of a title, a description, and a noncompliant code example and compliant solutions. The title is a concise, but sometimes imprecise, description of the guideline. The description specifies the normative requirements of the rule. The noncompliant code examples are examples of code that would constitute a violation of the guideline. The accompanying compliant solutions demonstrate equivalent code that does not violate the guideline or any other rules in the coding standard. Additionally, the rule may have one or more exceptions, often based on real-world code, which demonstrate compliant deviations from the normative rule text that do not constitute security vulnerabilities. Finally, each rule lists an assessment of the risks of not complying with the rule, a user-contributed list of tools that may be able to automatically detect violations of the rule, a list of related vulnerabilities and guidelines, and a bibliography.
Wrapping Up and Looking Ahead
A well-documented and enforceable coding standard is an essential element of coding in the C++ programming language. Coding standards encourage programmers to follow a uniform set of rules determined by the requirements of the project and organization rather than by the programmer's familiarity. Once established, these standards can be used as a metric to evaluate source code (using manual or automated processes).
The CERT C++ Coding Standard is entering the final technical review stage before its final publication later this fall. A draft version of the standard is available now for public review, and the CERT Secure Coding team welcomes feedback on the rules. Comments and feedback on each rule can be provided in the comments section at the bottom of each rules page.
We plan to publish the CERT C++ Coding Standard as a free PDF, similar to the release of the SEI CERT C Coding Standard. We appreciate all help in making sure that the standard reflects the best practices of the community. All constructive contributors will be recognized in the standard when it is published.
View the CERT C++ Coding Standard.