- A function shall have only one return.
Returns from nested code can add significant complexity.
- The goto statement shall be used to handle exceptions and early-exit conditions.
This rule along with the previous rule, helps to ensure that cleanup (or final statements) are executed.
- All functions return an int value; indicating success (0) or error.
Preferably, error values returned are selected from those in errno.h.
- Place constants on the left of equality comparisons.
"'Yoda conditions' are when you put the condition backwards" --Paul Griffiths/SO
- Do not create a universal character name through concatenation.
- Avoid side effects in arguments to unsafe macros
- Do not use preprocessor directives in invocations of function-like macros.
- Declare objects with appropriate storage durations.
- Declare identifiers before using them.
- Do not declare an identifier with conflicting linkage classification.
- Do not declare or define a reserved identifier.
- Use the correct syntax when declaring a flexible array member.
- Avoid information leakage in structure padding.
- Do not create incompatible declarations of the same function or object.
- Do not declare variables inside a switch statement before the first case label.
- Do not depend on the order of evaluation for side effects.
- Do not access a volatile object through a nonvolatile reference.
- Do not read uninitialized memory.
- Do not dereference null pointers.
- Do not modify objects with temporary lifetime.
- Do not cast pointers into more strictly aligned pointer types.
- Call functions with the correct number and type of arguments.
- Do not access a variable through a pointer of an incompatible type.
- Do not modify constant objects.
- Do not compare padding data.
- Avoid undefined behavior when using restrict-qualified pointers.
- Do not rely on side effects in operands to sizeof, _Alignof, or _Generic.
- Do not perform assignments in selection statements.
- Ensure that unsigned integer operations do not wrap
- Ensure that integer conversions do not result in lost or misinterpreted data
- Ensure that operations on signed integers do not result in overflow
- Ensure that division and remainder operations do not result in divide-by-zero errors
- Do not shift an expression by a negative number of bits or by greater than or equal to the number of bits that exist in the operand
- Use correct integer precisions
- Converting a pointer to integer or integer to pointer
- Do not use floating-point variables as loop counters
- Prevent or detect domain and range errors in math functions
- Ensure that floating-point conversions are within range of the new type
- Preserve precision when converting integral values to floating-point type
- Do not form or use out-of-bounds pointers or array subscripts
- Ensure size arguments for variable length arrays are in a valid range
- Do not subtract or compare two pointers that do not refer to the same array
- Do not add or subtract an integer to a pointer to a non-array object
- Guarantee that library functions do not form invalid pointers
- Do not add or subtract a scaled integer to a pointer
- Do not attempt to modify string literals
- Guarantee that storage for strings has sufficient space for character data and the null terminator
- Do not pass a non-null-terminated character sequence to a library function that expects a string
- Cast characters to unsigned char before converting to larger integer sizes
- Arguments to character-handling functions must be representable as an unsigned char
- Do not confuse narrow and wide character strings and functions
- Set errno to zero before calling a library function known to set errno, and check errno only after the function returns a value indicating failure
- Do not rely on indeterminate values of errno
- Detect and handle standard library errors
- Clean up thread-specific storage
- Do not destroy a mutex while it is locked
- Prevent data races when accessing bit-fields from multiple threads
- Avoid race conditions when using library functions
- Declare objects shared between threads with appropriate storage durations
- Avoid deadlock by locking in a predefined order
- Wrap functions that can spuriously wake up in a loop
- Do not call signal() in a multithreaded program
- Preserve thread safety and liveness when using condition variables
- Do not join or detach a thread that was previously joined or detached
- Do not refer to an atomic variable twice in an expression
- Wrap functions that can fail spuriously in a loop
- Do not use the rand() function for generating pseudorandom numbers
- Properly seed pseudorandom number generators
- Do not pass invalid data to the asctime() function
- Ensure that control never reaches the end of a non-void function
- Do not treat a predefined identifier as an object if it might only be implemented as a macro
- Do not call va_arg() on a va_list that has an indeterminate value
- Do not violate constraints
- Use the readlink() function properly
- Do not use vfork()
- Do not call putenv() with a pointer to an automatic variable as the argument
- Avoid race conditions while checking for the existence of a symbolic link
- Observe correct revocation order while relinquishing privileges
- Ensure that privilege relinquishment is successful
- Beware of race conditions when using fork and file descriptors
- Use the correct byte ordering when transferring data between systems
- Do not use signals to terminate threads
- Do not use threads that can be canceled asynchronously
- Do not unlock or destroy another POSIX thread's mutex
- When data must be accessed by multiple threads, provide a mutex and guarantee no adjacent data is also accessed
- Declare objects shared between POSIX threads with appropriate storage durations
- Avoid deadlock with POSIX threads by locking in predefined order
- Do not perform operations that can block while holding a POSIX lock
- Do not use more than one mutex for concurrent waiting operations on a condition variable
- Detect and handle POSIX library errors
- Properly pair allocation and deallocation functions
- Prefer inline or static functions to function-like macros.
- Use parentheses within macros and around parameter names. Parenthesize all parameter names found in macro definitions.
- Macro replacement lists should be parenthesized to protect any lower-precedence operators from the surrounding expression.
- Prefer type definitions (typedef) to macro definitions (#define) when encoding types.
- Do not reuse a standard header file name.
- Understand macro replacement when concatenating tokens or performing stringification.
- Enclose header files in an inclusion guard.
- Avoid using repeated question marks.
- Guarantee that header file names are unique.
- Do not replace secure functions with deprecated or obsolescent functions.
- Wrap multistatment macros in a do-while loop.
- Wrap multistatment macros in a do-while loop.
- Do not conclude macro definitions with a semicolon.
- Do not define unsafe macros.
- Use the Standard predefined macros to test for versions and features.
- 'const'-qualify immutable objects.
- Do not reuse variable names in subscopes.
- Use visually distinct identifiers.
- Use a static assertion to test the value of a constant expression.
- Do not declare more than one variable per declaration.
- Use typedefs of non-pointer types only.
- Use meaningful symbolic constants to represent literal values in program logic.
- Include the appropriate type information in function declarators.
- Properly encode relationships in constant definitions.
- Declare functions that return an errno error code with a return type of errno_t.
- Maintain the contract between the writer and caller of variadic functions.
- Understand the type issues associated with variadic functions.
- Implement abstract data types using opaque types.
- Declare function parameters tha are pointers to values not changed by the function as 'const'.
- Declare file-scope objects or functions that do not need external linkage as 'static'.
- Use "L," not "l," to indicate a long value.
- Beware of miscompiled volatile-qualified variables.
- Do not begin integer constants with 0 when specifying a decimal value.
- Minimize the scope of variables and functions.
- Explicitly specify void when a function accepts no arguments.
- Understand the storage of compound literals.
- Use volatile for data that cannot be cached.
- Guarantee that mutually visible identifiers are unique.
- Use parentheses for precedence of operation.
- Be aware of the short-circuit behavior of the logical AND and OR operators.
- Do not assume the size of a structure is the sum of the sizes of its members.
- Do not cast away a const qualification.
- Do not diminish the benefits of constants by assuming their values in expressions.
- Ensure pointer arithmetic is used correctly.
- Use sizeof to determine the size of a type or variable.
- Do not depend on the order of evaluation of subexpressions or the order in which side effects take place.
- Do not make assumptions regarding the layout of structures with bit-fields.
- Do not ignore values returned by functions.
- Treat relational and equality operators as if they were nonassociative.
- Beware of integer promotion when performing bitwise operations on integer types smaller than int.
- Do not place a semicolon on the same line as an if, for, or while statement.
- Do not compare function pointers to constant values.
- Do not perform bitwise operations in conditional expressions.
- Use braces for the body of an if, for, or while statement.
- Perform explicit tests to determine success, true and false, and equality.
- Understand the data model used by your implementation(s).
- Use rsize_t or size_t for all integer values representing the size of an object.
- Understand integer conversion rules.
- Enforce limits on integer values originating from tainted sources.
- Do not use input functions to convert character data if they cannot handle all possible inputs.
- Use strtol() or a related function to convert a string token to an integer.
- Use only explicitly signed or unsigned char type for numeric values.
- Verify that all integer values are in range.
- Ensure enumeration constants map to unique values.
- Do not assume a positive remainder when using the % operator.
- Do not make assumptions about the type of a plain int bit-field when used in an expression.
- Use bitwise operators only on unsigned operands.
- Avoid performing bitwise and arithmetic operations on the same data.
- Use intmax_t or uintmax_t for formatted IO on programmer-defined integer types.
- Do not make assumptions about representation of signed integers.
- Define integer constants in an implementation-independent manner.
- Evaluate integer expressions in a larger size before comparing or assigning to that size.
- Understand the limitations of floating-point numbers.
- Take care in rearranging floating-point expressions
- Avoid using floating-point numbers when precise computation is needed
- Detect and handle floating-point errors
- Check floating-point inputs for exceptional values
- Don't use denormalized numbers
- Convert integers to floating point for floating-point operations
- Cast the return value of a function that returns a floating-point type
- Understand how arrays work
- Do not apply the sizeof operator to a pointer when taking the size of an array
- Explicitly specify array bounds, even if implicitly defined by an initializer
- Represent characters using an appropriate type
- Adopt and implement a consistent plan for managing strings
- Sanitize data passed to complex subsystems
- Do not inadvertently truncate a string
- Use plain char for characters in the basic character set
- Use pointers to const when referring to string literals
- Do not assume that strtok() leaves the parse string unchanged
- Use the bounds-checking interfaces for remediation of existing string manipulation code
- Use managed strings for development of new string manipulation code
- Don't assume numeric values for expressions with type plain character
- Do not concatenate different type of string literals
- Do not specify the bound of a character array initialized with a string literal
- Adopt and implement a consistent and comprehensive error-handling policy
- Use ferror() rather than errno to check for FILE stream errors
- Avoid in-band error indicators
- Use runtime-constraint handlers when calling the bounds-checking interfaces
- Choose an appropriate termination strategy
- Application-independent code should provide error detection without dictating error handling
- Understand the termination behavior of assert() and abort()
- Prefer functions that support error checking over equivalent functions that don't
- Functions should validate their parameters
- Avoid laying out strings in memory directly before sensitive data
- Functions that read or write to or from an array should take an argument to specify the source or target size
- Create consistent interfaces and capabilities across related functions
- Provide a consistent and usable error-checking mechanism
- Use conformant array parameters
- Enforce type safety
- Avoid parameter names in a function prototype
- Compatible values should have the same type
- Avoid race conditions with multiple threads
- Acquire and release synchronization primitives in the same module, at the same level of abstraction
- Do not use volatile as a synchronization primitive
- Ensure visibility when accessing shared variables
- Join or detach threads even if their exit status is unimportant
- Do not perform operations that can block while holding a lock
- Ensure that every mutex outlives the data it protects
- Ensure that compound operations on shared variables are atomic
- Do not assume that a group of calls to independently atomic methods is atomic
- Avoid the ABA problem when using lock-free algorithms
- Compile cleanly at high warning levels
- Strive for logical completeness
- Use comments consistently and in a readable fashion
- Do not manipulate time_t typed values directly
- Beware of compiler optimizations
- Detect and remove dead code
- Character encoding: Use subset of ASCII for safety
- Character encoding: UTF8-related issues
- Incorporate diagnostic tests using assertions
- Detect and remove code that has no effect
- Detect and remove unused values
- Do not introduce unnecessary platform dependencies
- Do not depend on undefined behavior
- Finish every set of statements associated with a case label with a break statement
- Be careful while handling sensitive data, such as passwords, in program code
- For functions that return an array, prefer returning an empty array over a null value
- Do not use a switch statement to transfer control into a complex block
- Use robust loop termination conditions
- Use the setjmp(), longjmp() facility securely
- Beware of vendor-specific library and language differences
- Do not use deprecated or obsolescent functions
- Check for the existence of links when dealing with files
- Follow the principle of least privilege
- Avoid using PTHREAD_MUTEX_NORMAL type mutex locks
- Limit access to files by creating a jail
- Be specific when dynamically loading libraries
- Do not forcibly terminate execution
- Restrict privileges when spawning child processes
- Understand HANDLE inheritance
- Consider encrypting function pointers