V2021. Using assertions may cause the abnormal program termination in undesirable contexts.
The diagnostic rule has been added at users' request.
The analyzer has detected a macro call in the code that may cause a program crash. The standard 'assert' can be such a macro. Although its use reduces errors and vulnerabilities, its call may not be suitable for various scenarios. Such a scenario can appear when developers write library code.
Consider the following code:
[[noreturn]] void assertHandler();
#define ASSERT(expr) (!!(expr) || (assertHandler(), 0))
void foo(int i)
{
if (i < 0)
{
ASSERT(false && "The 'i' parameter must be non-negative");
}
}
The example shows a custom implementation of the 'assert' macro that calls a function that does not return a control flow to the caller function. The analyzer should issue a warning for the macro call. To do this, modify the code as follows:
[[noreturn]] void assertHandler(); // N1
#define ASSERT(expr) (!!(expr) || (assertHandler(), 0))
//V_PVS_ANNOTATIONS annotations.json // N2
//V_ASSERT_CONTRACT, assertMacro:ASSERT // N3
void foo(int i)
{
if (i < 0)
{
ASSERT(false); // <= V2021
}
}
In this example, you can see how to configure the custom macro detection mechanism.
Function markup as noreturn. The 'assertHandler' function inside the 'ASSERT' macro should be marked up as 'noreturn' (line N1). Standard attributes (C23 and C++11) enable developers to do markup:
[[noreturn]] void assertHandler(); // since C23 or C++11
The compiler-specific attributes (for example, MSVC or GCC / Clang) also enable developers to do markup:
__declspec(noreturn) void assertHandler(); // MSVC
__attribute__((noreturn)) void assertHandler(); // GCC, Clang
If it is not possible to modify the source code and mark up a function using an attribute, use the custom annotation system in the JSON format. To do this, create a JSON file with the following code:
{
"version": 1,
"annotations":
[
{
"type": "function",
"name": "assertHandler",
"parameters": [],
"attributes": [ "noreturn" ]
},
....
]
}
Then, enable the file during the analysis using one of the described approaches. In the example, you can look at the line N2 to see how it works.
Macro markup. The analyzer should consider that code execution may be terminated because of the 'ASSERT' macro. To do this, write the comment like in the line N3. Learn more about the mechanism here.
Naming functions with enabled macro call
Users can disable the diagnostic rule for a function if they are confident that using the macro is safe in this context. To do this, use the function markup where the macro is called with a comment:
//-V2021_IGNORE_ASSERT_IN_FUNCTION, function: My::Qualified::Name
Note. The diagnostic rule is issued on the standard 'assert'. So, it is disabled by default to prevent the issuance of numerous warnings.
To enable the diagnostic rule, use the enabling mechanism via a comment or the '#pragma pvs' directive.
This diagnostic is classified as:
|