GitHub
CERT Secure Coding

Coding Style Guidelines

This document details the coding style guidelines to be used within the CERT C and C++ Coding Standards. It is not meant as a general-purpose style guideline for production code and is not intended to be viewed as a "secure coding style guideline." It is only meant as a mechanism to ensure the coding standards have a uniform coding style. Note that deviation from these rules is always acceptable if the substantive content of the rule requires it. For instance, a rule about K&R-style C functions is not required to have the code examples include function declarations with prototypes, despite that being a style guideline.

Basics

  • NCCE source code should have the standard "red box" background. CS source code should have the standard "blue box" background, as should code examples that are showing a valid exception to the rule. Informative source code that is neither NCCE nor CS/exception should have no background.
  • All NCCE and CS code examples must compile without requiring user modification unless otherwise noted in the text surrounding the example code. The only exception to this rule is for code samples pulled from snippets of other source (such as when demonstrating a vulnerability from a CVE). In this case, the surrounding text should cite the source of the code (preferably with a link so that the reader can find more context for the source code). Some web hosted C and C++ compilers that you can use for testing include:

Note that the examples must compile but are not required to link. Not every example needs to have a main function, or requires function definitions, for instance.

If you have a code example that fixes a problem by being ill-formed, it should use a red box and be a noncompliant code example, followed by a well-formed compliant solution. For example, we have a C++ NCCE that uses auto_ptr. A second NCCE replaces auto_ptr with unique_ptr, rendering the code ill-formed. While this is an NCCE it is obvious because the compiler will complain. There is a subsequent CS using unique_ptr that is compile-able. This is in VOID MEM00-CPP. Don't use auto_ptr where copy semantics might be expected .

  • Code should have as few #include statements as possible, and only include the functionality required for the code example (from the canonical header for that functionality, not transitively via some other intermediary header). e.g., when the code example requires a variable of type size_t , include stddef.h or cstddef directly, instead of obtaining the type through another header, such as string.h . Includes should be listed in alphabetical order when possible.
  • When refering to code entities from the surrounding text (including file header names, function names, variable names, etc), the entities should be written in monospace font .
  • All NCCEs should only violate the rule being discussed, and comply with secure coding recommendations unless otherwise noted in the surrounding text. All CSs should comply with all secure coding rules and recommendations.
  • Code should not exceed an 80 column limit, including comments.
  • <thought>Run clang-format over the code, using a format configuration file that I gin up and expose from this page. This takes care of all spacing, column limits, where-do-line-breaks-go kind of questsions.</thought>

Broad Details

These details apply only to code built to illustrate an example. They do not apply to pre-existing code, such as excerpts from a bug report or open-source software.

Java code should use the standard Java conventions as mandated by Sun, with the single exception that indentation is two spaces rather than four.

The following details apply to C & C++ code

  • All non-builtin type and enumerator names should be in PascalCase . e.g., struct S; typedef int MyAwesomeInt; template <typename T> , enum MyEnum { MyFirstValue, MySecondValue }; etc.
  • All function names should be in snake_case . e.g., void func(); , int my_awesome_int_func(void); , struct S { void cool_func(); }; etc.
    • Excluded from this requirement are: constructors and destructors.
  • All variable names should be in camelCase . e.g., int i; std::string userPassword; , struct S { int i; char smallData; }; etc.
  • All macro definition names should be in UPPERCASE. e.g., #define FOO(x) (x)
  • Do not use Hungarian notation.
  • Use /**/ for multiline comments, use // for single-line comments, in both C and C++ code. Comments should be a complete sentence or noun phrase (with proper spelling, grammar, capitalization, and punctuation), except when given an imperative (e.g., Handle error).
  • Use two spaces for indentation. Do not tabs. Indent all code consistently.

Function Details

  • When writing C code (including C++ code marked as extern "C" ), always provide a function prototype. e.g., void func(void); instead of void func();
  • When writing C++ code, do not include a parameter type list for a function that accepts no arguments. e.g., void func(); instead of void func(void);

Control Flow Details

  • All control flow statements should use a compound statement block instead of a single, non-compound statement. e.g., if (x) { x = y; } instead of if (x) x = y;
  • Do not use else after something that interrupts control flow ( return , break , etc). This reduces the amount of indented code and makes the examples more readable. e.g., if (x) { return; } else { /* Do not do this; remove the else. */ }

Microscopic Details

  • Put spaces between an open parenthesis only in control flow statements. e.g., if (x); instead of if(x); Do not put spaces in function calls or function-like macro invocations. e.g., foo(1, 2); instead of foo (1, 2); or foo( 1, 2 );
  • Prefix and suffix binary operators with spaces. e.g. 1 + 1 * 2 instead of 1+1*2 .

C++ Details

  • Do not use auto unless the type is explicitly spelled out within the remainder of the statement. e.g., int good = g(); instead of auto bad = g(); auto *good = dynamic_cast<SomeType *>(bar);
  • Do not use using namespace XXX; at file scope (it is permissible at function scope, but should be used very sparingly).
  • Since we now care about C++14 more than C++98, use >> rather than > > to close out nested template declarations. e.g., std::vector<Foo<int>>; instead of std::vector<Foo<int> >;

C Details

  • Since we now care about C11 more than C89, put variable declarations as close to their use as possible instead of in a group at the top of a function definition. Declare the loop induction variable as part of a for loop instead of at function scope.