44<qhelp >
55<overview >
66<p >
7- The expression <code >ptr + a < ptr</code > is equivalent to <code >a <
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 < ptr</code > with <code >false</code >.
7+ When checking for integer overflow, you may often write tests like
8+ <code >p + i < 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 < 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 < ARRAY_LENGTH</code >.
2523If 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 < 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 < p_end - ptr</code >.
24+ <code >ptr</code > and <code >p_end</code >, write <code >i < 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 < p_end - ptr</code >.
3028</p >
3129</recommendation >
3230<example >
@@ -43,14 +41,14 @@ overflows and wraps around.
4341<p >
4442In both of these checks, the operations are performed in the wrong order.
4543First, 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.
4745But once undefined behavior has happened in the pointer addition, it cannot
4846be recovered from: it's too late to perform the range check after a possible
4947pointer overflow.
5048</p >
5149
5250<p >
53- While it's not the subject of this query, the expression <code >ptr + a <
51+ While it's not the subject of this query, the expression <code >ptr + i <
5452ptr_end</code > is also an invalid range check. It's undefined behavor in
5553C/C++ to create a pointer that points more than one past the end of an
5654allocation.
0 commit comments