...
The assert
macro expands to a void expression:
Code Block |
---|
#include <assert.h>
void assert(scalar expression);
|
When it is executed, if expression
(which must have a scalar type) is false, the assert
macro outputs information about the failed assertion (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 was omitted for the unsigned multiplication based on the assumption that MAX_TABLE_SIZE * sizeof(char *)
cannot exceed SIZE_MAX
. While Although we know this is true, it cannot do any harm to codify this assumption.
Code Block | ||||
---|---|---|---|---|
| ||||
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 deployed by defining the NDEBUG
macro (typically as a flag passed to the compiler). Consequently, assertions should be used to protect against incorrect programmer assumptions and not for runtime error checking.
Assertions should never be used to verify the absence of runtime (as opposed to logic) errors, such as:
- invalid Invalid user input (including command-line arguments and environment variables)
- file File errors (for example, errors opening, reading or writing files)
- network Network errors (including network protocol errors)
- out Out-of-memory conditions (for example,
malloc()
or similar failures) - system System resource exhaustion (for example, out-of-file descriptors, processes, threads)
- system System call errors (for example, errors executing files, locking or unlocking mutexes)
- invalid Invalid permissions (for example, file, memory, user)
...
In particular, assertions are generally unsuitable for server programs or embedded systems in deployment. A failed assertion can lead to a denial-of-service attack if triggered by a malicious user, such as if size
were being derived, in some way derived , from client input. In such situations, a soft failure mode, such as writing to a log file and rejecting the request, is more appropriate.
Code Block | ||||
---|---|---|---|---|
| ||||
if (size > SIZE_MAX / sizeof(char *)) { fprintf(log_file, "%s: size %zu exceeds %zu bytes\n", log_file, __FILE__ ":, size %zu exceeds, SIZE_MAX / sizeof(char *)\n", size ); size = SIZE_MAX / sizeof(char *); } table_size = size * sizeof(char *); |
...
Noncompliant Code Example (malloc()
)
The This noncompliant code example below uses the assert()
macro to verify that memory allocation succeeded. Because memory availability depends on the overall state of the system and may can become exhausted at any point during a process lifetime, a robust program must be prepared to gracefully handle and recover from its exhaustion. ThereforeConsequently, using the assert()
macro to verify that a memory allocation succeeded would be inappropriate as because doing so might lead to an abrupt termination of the process and open up , opening the possibility of a denial-of-service attack. See also MEM11-C. Do not assume infinite heap space and void MEM32-C. Detect and handle memory allocation errors.
Code Block | ||||
---|---|---|---|---|
| ||||
char *dupstring(const char *c_str) { size_t len; char *dup; len = strlen(c_str); dup = (char *)malloc(len + 1); assert(NULL != dup); memcpy(dup, c_str, len + 1); return dup; } |
...
Compliant Solution (malloc()
)
The This compliant solution below demonstrates how to detect and handle possible memory exhaustion.:
Code Block | ||||
---|---|---|---|---|
| ||||
char *dupstring(const char *c_str) { size_t len; char *dup; len = strlen(c_str); dup = (char*)malloc(len + 1); /* detectDetect and handle memory allocation error */ if (NULL == dup) { return NULL; } memcpy(dup, c_str, len + 1); return dup; } |
...
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-C |
Low |
Unlikely |
High | P1 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| LANG.FUNCS.ASSERTS | Not enough assertions | ||||||
| ASSERT_SIDE_EFFECT | Can detect the specific instance where assertion contains an operation/function call that may have a side effect | |||||||
Parasoft C/C++test |
| CERT_C-MSC11-a | Assert liberally to document internal assumptions and invariants |
Related Vulnerabilities
Search for for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
...
Related Guidelines
CERT C Secure Coding Standard | ERR00-C. Adopt and implement a consistent and comprehensive error-handling policy |
SEI CERT C++ |
...
...
...
...
Wiki Markup |
---|
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.2.1, "Program diagnostics" |
CWE-190, Reachable assertion |
...
MSC10-C. Character Encoding - UTF8 Related Issues 49. Miscellaneous (MSC) MSC12-C. Detect and remove code that has no effect