mirror of
https://github.com/github/codeql.git
synced 2025-12-20 18:56:32 +01:00
[zlaski/pointer-overflow-check] Refine query to exclude macros (other than 'assert').
This commit is contained in:
@@ -1,3 +1,3 @@
|
|||||||
bool check_pointer_overflow(P *ptr, P *ptr_end) {
|
bool check_pointer_overflow(P *ptr, P *ptr_end) {
|
||||||
return ptr + 4 >= ptr_end; // GOOD
|
return ptr_end - ptr >= 4; // GOOD
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<qhelp>
|
<qhelp>
|
||||||
<overview>
|
<overview>
|
||||||
<p>
|
<p>
|
||||||
When checking for out-of-range pointer values, one might write tests like
|
When checking for out-of-range pointer values, we might write tests like
|
||||||
<code>p + a < p</code> and check if the value "wraps around".
|
<code>p + a < p</code> and check if the value "wraps around".
|
||||||
Such a test is wrong in that it relies on the overflow of <code>p + a</code>,
|
Such a test is wrong in that it relies on the overflow of <code>p + a</code>,
|
||||||
which has undefined behavior. In fact, many optimizing compilers will remove
|
which has undefined behavior. In fact, many optimizing compilers will remove
|
||||||
@@ -18,13 +18,12 @@ the operating system) or nonexistent.
|
|||||||
<recommendation>
|
<recommendation>
|
||||||
<p>
|
<p>
|
||||||
When checking for an out-of-range pointer, compare the pointer
|
When checking for an out-of-range pointer, compare the pointer
|
||||||
value <code>p</code> against a known value <code>p_max</code> representing
|
value <code>p</code> against a known pointer value <code>p_max</code> representing
|
||||||
the highest allowable memory address. Ideally, <code>p_max</code> should
|
the highest allowable memory address. The <code>p_max</code> pointer should
|
||||||
point just past the end of a data structure, such as an array or a vector.
|
point inside or just past the end of a defined memory region, such that
|
||||||
For lower-level work, it should point at the highest address in the program
|
<code>p + a <= p_max</code>. Since we do not wish to evaluate <code>p + a</code>
|
||||||
heap. It is also important that <code>p + a</code> points at a valid object
|
(which may result in undefined behavior), we rewrite the inequality as
|
||||||
and that <code>a</code> is small enough so that the expression <code>p + a</code>
|
<code>p_max - p > a</code>.
|
||||||
does not itself overflow.
|
|
||||||
</p>
|
</p>
|
||||||
</recommendation>
|
</recommendation>
|
||||||
<example>
|
<example>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* @description Testing for out-of-range pointers by adding a value to a pointer
|
* @description Testing for out-of-range pointers by adding a value to a pointer
|
||||||
* to see if it "wraps around" is dangerous because it relies
|
* to see if it "wraps around" is dangerous because it relies
|
||||||
* on undefined behavior and may lead to attempted use of
|
* on undefined behavior and may lead to attempted use of
|
||||||
* nonexistent or inaccessible memory locations
|
* nonexistent or inaccessible memory locations.
|
||||||
* @kind problem
|
* @kind problem
|
||||||
* @problem.severity warning
|
* @problem.severity warning
|
||||||
* @precision high
|
* @precision high
|
||||||
@@ -14,12 +14,23 @@
|
|||||||
|
|
||||||
import cpp
|
import cpp
|
||||||
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||||
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
|
||||||
|
class AssertMacro extends Macro {
|
||||||
|
AssertMacro() {
|
||||||
|
getName() = "assert" or
|
||||||
|
getName() = "_ASSERT" or
|
||||||
|
getName() = "_ASSERTE" or
|
||||||
|
getName() = "_ASSERT_EXPR"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
from RelationalOperation ro, PointerAddExpr add, Expr expr1, Expr expr2
|
from RelationalOperation ro, PointerAddExpr add, Expr expr1, Expr expr2
|
||||||
where
|
where
|
||||||
ro.getAnOperand() = add and
|
ro.getAnOperand() = add and
|
||||||
add.getAnOperand() = expr1 and
|
add.getAnOperand() = expr1 and
|
||||||
ro.getAnOperand() = expr2 and
|
ro.getAnOperand() = expr2 and
|
||||||
globalValueNumber(expr1) = globalValueNumber(expr2)
|
globalValueNumber(expr1) = globalValueNumber(expr2) and
|
||||||
|
not exists(MacroInvocation mi |
|
||||||
|
mi.getAnAffectedElement() = add and not mi.getMacro() instanceof AssertMacro
|
||||||
|
)
|
||||||
select ro, "Pointer out-of-range check relying on pointer overflow is undefined."
|
select ro, "Pointer out-of-range check relying on pointer overflow is undefined."
|
||||||
|
|||||||
Reference in New Issue
Block a user