Skip to content

Commit 74ca0e4

Browse files
authored
Merge pull request #2334 from rdmarsh2/rdmarsh/cpp/reword-pointeroverflow-qhelp
C++: simplify PointerOverflow.qhelp
2 parents e7705b0 + 85314c4 commit 74ca0e4

File tree

3 files changed

+21
-23
lines changed

3 files changed

+21
-23
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
bool not_in_range(T *ptr, T *ptr_end, size_t a) {
2-
return ptr + a >= ptr_end || ptr + a < ptr; // BAD
1+
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
2+
return ptr + i >= ptr_end || ptr + i < ptr; // BAD
33
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
bool not_in_range(T *ptr, T *ptr_end, size_t a) {
2-
return a >= ptr_end - ptr; // GOOD
1+
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
2+
return i >= ptr_end - ptr; // GOOD
33
}

cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.qhelp

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,27 @@
44
<qhelp>
55
<overview>
66
<p>
7-
The expression <code>ptr + a &lt; ptr</code> is equivalent to <code>a &lt;
8-
0</code>, and an optimizing compiler is likely to make that replacement,
9-
thereby removing a range check that might have been necessary for security.
10-
If <code>a</code> is known to be non-negative, the compiler can even replace <code>ptr +
11-
a &lt; ptr</code> with <code>false</code>.
7+
When checking for integer overflow, you may often write tests like
8+
<code>p + i &lt; p</code>. This works fine if <code>p</code> and
9+
<code>i</code> are unsigned integers, since any overflow in the addition
10+
will cause the value to simply "wrap around." However, using this pattern when
11+
<code>p</code> is a pointer is problematic because pointer overflow has
12+
undefined behavior according to the C and C++ standards. If the addition
13+
overflows and has an undefined result, the comparison will likewise be
14+
undefined; it may produce an unintended result, or may be deleted entirely by an
15+
optimizing compiler.
1216
</p>
1317

14-
<p>
15-
The reason is that pointer arithmetic overflow in C/C++ is undefined
16-
behavior. The optimizing compiler can assume that the program has no
17-
undefined behavior, which means that adding a positive number to <code>ptr</code> cannot
18-
produce a pointer less than <code>ptr</code>.
19-
</p>
2018
</overview>
2119
<recommendation>
2220
<p>
23-
To check whether an index <code>a</code> is less than the length of an array,
24-
simply compare these two numbers as unsigned integers: <code>a &lt; ARRAY_LENGTH</code>.
21+
To check whether an index <code>i</code> is less than the length of an array,
22+
simply compare these two numbers as unsigned integers: <code>i &lt; ARRAY_LENGTH</code>.
2523
If the length of the array is defined as the difference between two pointers
26-
<code>ptr</code> and <code>p_end</code>, write <code>a &lt; p_end - ptr</code>.
27-
If a is <code>signed</code>, cast it to <code>unsigned</code>
28-
in order to guard against negative <code>a</code>. For example, write
29-
<code>(size_t)a &lt; p_end - ptr</code>.
24+
<code>ptr</code> and <code>p_end</code>, write <code>i &lt; p_end - ptr</code>.
25+
If <code>i</code> is signed, cast it to unsigned
26+
in order to guard against negative <code>i</code>. For example, write
27+
<code>(size_t)i &lt; p_end - ptr</code>.
3028
</p>
3129
</recommendation>
3230
<example>
@@ -43,14 +41,14 @@ overflows and wraps around.
4341
<p>
4442
In both of these checks, the operations are performed in the wrong order.
4543
First, an expression that may cause undefined behavior is evaluated
46-
(<code>ptr + a</code>), and then the result is checked for being in range.
44+
(<code>ptr + i</code>), and then the result is checked for being in range.
4745
But once undefined behavior has happened in the pointer addition, it cannot
4846
be recovered from: it's too late to perform the range check after a possible
4947
pointer overflow.
5048
</p>
5149

5250
<p>
53-
While it's not the subject of this query, the expression <code>ptr + a &lt;
51+
While it's not the subject of this query, the expression <code>ptr + i &lt;
5452
ptr_end</code> is also an invalid range check. It's undefined behavor in
5553
C/C++ to create a pointer that points more than one past the end of an
5654
allocation.

0 commit comments

Comments
 (0)