Implement Exceptions in User-Defined Defects
In constructing user-defined defects, you can define exceptions to defects. An exception is a circumstance where the conditions for the defect are satisfied, but you do not want the defect to be reported. Such exceptions can make your defect more relevant for your use cases and make it easier to review results. This topic shows how you can add an exception to your defect. For more information on developing user-defined defects:
User-Defined Defect with False Positive Result
Consider a user-defined defect return_not_checked that checks if the
return value of a function is immediately discarded and not explicitly cast to
void:
defect return_not_checked =
when
Cpp.CallSite.is(&CS)
and CS.immediatelyDiscarded()
and not CS.explicitlyCastToVoid()
and CS.toString(&name)
raise "Return value immediately discarded: \"{name}\""
on CS#include <iostream>
#define DEBUG_MODE true
int getValue() { return 42; }
int compute() { return 100; }
int calculate() { return 200; }
int debugLog(const char *msg)
{
std::cout << msg << std::endl; //defect
return 0;
}
struct Math
{
int add(int a, int b) { return a + b; }
int multiply(int a, int b) { return a * b; }
};
int main()
{
Math m;
// Discarded function calls
getValue(); //defect
compute(); //defect
m.add(5, 10); //defect
m.multiply(3, 4); //defect
// Explicitly cast to void
(void)calculate();
(void)m.add(1, 2);
// Assigned to variables
int result = getValue();
int sum = m.multiply(2, 3);
// Debug function - return value SHOULD be discarded
if (DEBUG_MODE)
{
debugLog("Debug message"); //defect
}
return 0;
}
debugLog
is used for debugging and always returns 0. To exclude such functions
from your result, implement an exception to the in the defect definition.Define Exception
Use the except statement to create an exception for the
defect:
defect inside_compound_check =
when
Cpp.CallSite.is(&CS)
and CS.immediatelyDiscarded()
and not CS.explicitlyCastToVoid()
and CS.toString(&name)
except returnNotImportant(CS)
raise "Return value immediately discarded: \"{name}\""
on CS
returnNotImportant is
satisfied:predicate returnNotImportant(Cpp.CallSite.CallSite CS){
return CS.callee(&f) and f.name(&name) and name.startsWith("debug")
}true if the invoked
function has a name that stars with the string debug. After running a an
analysis with this defect, the violation on debugLog() is no longer
reported.