You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 8 Next »

Incorporate diagnostic tests into your program. The assert() macro is one convenient mechanism for interactive programs.

The assert macro expands to a void expression:

#include <assert.h>
void assert(scalar expression);

When it is executed, if expression (which must have a scalar type) is false, the assert macro writes information about the particular call that failed (including the text of the argument, the name of the source file, the source line number, and the name of the enclosing function) on the standard error stream in an implementation-defined format and calls the abort() function.

In the following example, the test for integer wrap has been omitted for the unsigned multiplication based on the assumption that MAX_TABLE_SIZE * sizeof(char *) cannot exceed SIZE_MAX. While we know this is true, it cannot do any harm to codify this assumption.

assert(size <= SIZE_MAX/sizeof(char *));
table_size = size * sizeof(char *);

Assertions are primarily intended for use during debugging, and are generally turned off before code is shipped by defining NDEBUG (typically as a flag passed to the compiler). Consequently, assertions are only useful to protect against incorrect assumptions, and are not intended for runtime error checking.

Examples of improper assertions include:

  • invalid user input
  • file not found
  • out of memory
  • invalid permissions

Code that protects against a buffer overflow, for example, cannot be implemented as an assertion because this code must be presented in the deployed executable.

In particular, assertions are generally unsuitable for server programs or embedded systems. A failed assertion could lead to denial of service if a hacker discovered how to trigger it, e.g. if size were in some way derived from client input.  In such situations, a soft failure mode such as writing to a log file is more appropriate.

if (size > SIZE_MAX/sizeof(char *)) {
  fprintf(log_file, __FILE__ ": size %zu exceeds SIZE_MAX/sizeof(char *)\n", size);
  size = SIZE_MAX/sizeof(char *);
}
table_size = size * sizeof(char *);

Risk Assessment

Assertions are a valuable diagnostic tool for finding and eliminating software defects that may result in vulnerabilities. The absence of assertions, however, does not mean that code is incorrect.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MSC11-A

1 (low)

1 (unlikely)

3 (low)

P3

L3

References

[[ISO/IEC 9899-1999]] Section 7.2.1, "Program diagnostics"


MSC10-A. Character Encoding - UTF8 Related Issues      14. Miscellaneous (MSC)       MSC12-A. Detect and remove code that has no effect

  • No labels