Diagnostic tests can be incorporated into programs by using the assert
statement. Assertions are primarily intended for use during debugging and are often turned off before code is deployed by using the -disableassertions
(or -da
) Java runtime switch. 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 user input (including command-line arguments and environment variables)
- File errors (for example, errors opening, reading, or writing files)
- Network errors (including network protocol errors)
- Out-of-memory conditions (when the Java Virtual Machine cannot allocate space for a new object and the garbage collector cannot make sufficient space available)
- System resource exhaustion (for example, out-of-file descriptors, processes, threads)
- System call errors (for example, errors executing files, locking or unlocking mutexes)
- Invalid permissions (for example, file, memory, user)
Code that protects against an I/O error, for example, cannot be implemented as an assertion because it must be present in the deployed executable.
Assertions are generally unsuitable for server programs or embedded systems in deployment. A failed assertion can lead to a denial-of-service (DoS) attack if triggered by a malicious user. In such situations, a soft failure mode, such as writing to a log file and rejecting the request, is more appropriate.
Noncompliant Code Example
This noncompliant code example uses the assert
statement to verify that input was available:
BufferedReader br; // Set up the BufferedReader br String line; // ... line = br.readLine(); assert line != null;
Because input availability depends on the user and can be exhausted at any point during program execution, a robust program must be prepared to gracefully handle and recover from the unavailability of input. However, using the assert
statement to verify that some significant input was available is inappropriate because it might lead to an abrupt termination of the process, resulting in a denial of service.
Compliant Solution
This compliant solution demonstrates the recommended way to detect and handle unavailability of input:
BufferedReader br; // Set up the BufferedReader br String line; // ... line = br.readLine(); if (line == null) { // Handle error }
Applicability
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 bug-free.
In general, the misuse of the assert
statement for runtime checking rather than checking for logical errors cannot be detected automatically.
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Parasoft Jtest | 2024.1 | CERT.MSC60.ASSERT | Do not use assertions in production code |
2 Comments
James Ahlborn
This rule seems to recommend using assertions, but most of the rule talks about the dangers of using them.
frankly, my personal opinion is that assertions are generally useless for the reasons mentioned here, and others. unless you work in a code base where the use of assertions is very strictly governed, you invariably run into cases where they were used inconsistently, or, even worse, turning off assertions changes runtime behavior such that something stops working. regardless of the reason, eventually it is decided that assertions can't be disabled, so now they run all the time. if you have any assertions which dramatically impact performance, then you need to go back and remove them from the code. long story short, don't use assertions cause it's really hard to maintain them in a codebase. put runtime checks in the code and test time checks in your unit test code.
David Svoboda
I've changed the title and tweaked the intro to reflect that this rule means to limit when to use assertions, rather than promote their use.