mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Adds another redundant null check rule
This commit is contained in:
11
cpp/ql/src/Likely Bugs/RedundantNullCheckParam.cpp
Normal file
11
cpp/ql/src/Likely Bugs/RedundantNullCheckParam.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
void test(char *arg1, int *arg2) {
|
||||
if (arg1[0] == 'A') {
|
||||
if (arg2 != NULL) {
|
||||
*arg2 = 42;
|
||||
}
|
||||
}
|
||||
if (arg1[1] == 'B')
|
||||
{
|
||||
*arg2 = 54;
|
||||
}
|
||||
}
|
||||
29
cpp/ql/src/Likely Bugs/RedundantNullCheckParam.qhelp
Normal file
29
cpp/ql/src/Likely Bugs/RedundantNullCheckParam.qhelp
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>This rule finds comparisons of a function parameter to null that occur when in another path the parameter is dereferenced without a guard check. It's
|
||||
likely either the check is not required and can be removed, or it should be added before the dereference
|
||||
so that a null pointer dereference does not occur.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>A check should be added to before the dereference, in a way that prevents a null pointer value from
|
||||
being dereferenced. If it's clear that the pointer cannot be null, consider removing the check instead.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<sample src="RedundantNullCheckParam.cpp" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
<a href="https://www.owasp.org/index.php/Null_Dereference">
|
||||
Null Dereference
|
||||
</a>
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
59
cpp/ql/src/Likely Bugs/RedundantNullCheckParam.ql
Normal file
59
cpp/ql/src/Likely Bugs/RedundantNullCheckParam.ql
Normal file
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @name Redundant null check or missing null check
|
||||
* @description Checking a parameter for nullness in one path,
|
||||
* and not in another is likely to be a sign that either
|
||||
* the check can be removed, or added in the other case.
|
||||
* @kind problem
|
||||
* @id cpp/redundant-null-check-param
|
||||
* @problem.severity recommendation
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-476
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
predicate blockDominates(Block check, Block access) {
|
||||
check.getLocation().getStartLine() <= access.getLocation().getStartLine() and
|
||||
check.getLocation().getEndLine() >= access.getLocation().getEndLine()
|
||||
}
|
||||
|
||||
predicate isCheckedInstruction(VariableAccess unchecked, VariableAccess checked) {
|
||||
checked =
|
||||
any(VariableAccess va |
|
||||
va.getTarget() = unchecked.getTarget()
|
||||
) and
|
||||
//Simple test if the first access in this code path is dereferenced
|
||||
not dereferenced(checked) and
|
||||
blockDominates(checked.getEnclosingBlock(), unchecked.getEnclosingBlock())
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
predicate candidateResultUnchecked(VariableAccess unchecked) {
|
||||
not isCheckedInstruction(unchecked, _)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
predicate candidateResultChecked(VariableAccess check, EqualityOperation eqop, Parameter param) {
|
||||
//not dereferenced to check against pointer, not its pointed value
|
||||
not dereferenced(check) and
|
||||
//assert macros are not taken into account
|
||||
not check.isInMacroExpansion() and
|
||||
// is part of a comarison against some constant NULL
|
||||
eqop.getAnOperand() = check and eqop.getAnOperand() instanceof NullValue and
|
||||
// this function parameter is not overwritten
|
||||
count(param.getAnAssignment()) = 0
|
||||
}
|
||||
|
||||
from VariableAccess unchecked, VariableAccess check, EqualityOperation eqop, Parameter param
|
||||
where
|
||||
// a dereference
|
||||
dereferenced(unchecked) and
|
||||
// for a function parameter
|
||||
unchecked.getTarget() = param and
|
||||
check.getTarget() = param and
|
||||
// which is once checked
|
||||
candidateResultChecked(check, eqop, param) and
|
||||
// and which has not been checked before in this code path
|
||||
candidateResultUnchecked(unchecked)
|
||||
select check, "This null check is redundant because the value is $@ ", unchecked, "dereferenced here"
|
||||
Reference in New Issue
Block a user