Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9407ba1

Browse files
committed
[zlaski/pointer-overflow-check] Initial version.
1 parent 770a470 commit 9407ba1

7 files changed

Lines changed: 99 additions & 0 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bool check_pointer_overflow(P *ptr) {
2+
return ptr + 0x12345678 < ptr; // BAD
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bool check_pointer_overflow(P *ptr, P *ptr_end) {
2+
return ptr + 4 >= ptr_end; // GOOD
3+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
When checking for out-of-range pointer values, one might write tests like
8+
<code>p + a &lt; p</code> and check if the value "wraps around".
9+
Such a test is wrong in that it relies on the overflow of <code>p + a</code>,
10+
which is undefined behavior. In fact, many optimizing compilers will remove
11+
<code>p + a &lt; p</code> altogether and replace it with the value <code>0</code>
12+
(<code>false</code>). Conversely, should <code>p + a</code> <i>not</i> overflow,
13+
the programmer may erroneously assume that the memory location <code>p + a</code>
14+
is accessible to the program, even though it may be inaccessible (protected by
15+
the operating system) or nonexistent.
16+
</p>
17+
</overview>
18+
<recommendation>
19+
<p>
20+
When checking for an out-of-range pointer, compare the pointer
21+
value <code>p</code> against a known value <code>p_max</code> representing
22+
the highest allowable memory address. Ideally, <code>p_max</code> should
23+
point just past the end of a data structure, such as an array or a vector.
24+
For lower-level work, it should point at the highest address in the program
25+
heap. It is also important that <code>p + a</code> points at a valid object
26+
and that <code>a</code> is small enough so that the expression <code>p + a</code>
27+
does not itself overflow.
28+
</p>
29+
</recommendation>
30+
<example>
31+
<p>
32+
In the first example, a constant value is being added to a pointer and
33+
then tested for "wrap around". Should the test fail, the developer
34+
might assume that memory location <code>ptr + 0x12345678</code> is a
35+
valid one for the program to use, even though it may be either
36+
inaccessible (protected from the current process by the operating
37+
system) or nonexistent. Furthermore, it may be impossible to tell when
38+
the test succeeds, since pointer overflow has undefined behavior.
39+
</p>
40+
<sample src="PointerOverflowCheck-bad.cpp" />
41+
<p>
42+
The next example shows how to properly check for an out-of-range pointer.
43+
In order to do so, we need to obtain the value <code>ptr_end</code>
44+
representing the highest allowable memory address. In this case,
45+
the address lies just beyond the end of an array.
46+
</p>
47+
<sample src="PointerOverflowCheck-good.cpp" />
48+
</example>
49+
<references>
50+
<li><a href="https://blog.regehr.org/archives/1395">Pointer Overflow Checking [Embedded in Academia]</a></li>
51+
<li><a href="https://lwn.net/Articles/278137/">GCC and pointer overflows [LWN]</a></li>
52+
</references>
53+
</qhelp>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* @name Dangerous pointer out-of-range check
3+
* @description Testing for out-of-range pointers by adding a value to a pointer
4+
* to see if it "wraps around" is dangerous because it relies
5+
* on undefined behavior and may lead to attempted use of
6+
* nonexistent or inaccessible memory locations
7+
* @kind problem
8+
* @problem.severity warning
9+
* @precision high
10+
* @id cpp/pointer-overflow-check
11+
* @tags reliability
12+
* security
13+
*/
14+
15+
import cpp
16+
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
17+
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
18+
19+
from RelationalOperation ro, PointerAddExpr add, Expr expr1, Expr expr2
20+
where
21+
ro.getAnOperand() = add and
22+
add.getAnOperand() = expr1 and
23+
ro.getAnOperand() = expr2 and
24+
globalValueNumber(expr1) = globalValueNumber(expr2)
25+
select ro, "Pointer out-of-range check relying on pointer overflow is undefined."
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| test.cpp:6:12:6:33 | ... < ... | Pointer out-of-range check relying on pointer overflow is undefined. |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Likely Bugs/Memory Management/PointerOverflowCheck.ql
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct P { int a, b; };
2+
bool check_pointer_overflow(P *ptr) {
3+
// x86-64 gcc 9.2 -O2: deleted
4+
// x86-64 clang 9.9.9 -O2: deleted
5+
// x64 msvc v19.22 /O2: not deleted
6+
return ptr + 0x12345678 < ptr; // BAD
7+
}
8+
bool check_pointer_overflow(P *ptr, P *ptr_end) {
9+
// x86-64 gcc 9.2 -O2: not deleted
10+
// x86-64 clang 9.0.0 -O2: not deleted
11+
// x64 msvc v19.22 /O2: not deleted
12+
return ptr + 4 >= ptr_end; // GOOD
13+
}

0 commit comments

Comments
 (0)