@@ -12,36 +12,39 @@ which has undefined behavior. In fact, many optimizing compilers will remove
1212(<code >false</code >). Conversely, should <code >p + a</code > <i >not</i > overflow,
1313the programmer may erroneously assume that the memory location <code >p + a</code >
1414is accessible to the program, even though it may be inaccessible (protected by
15- the operating system) or nonexistent.
15+ the operating system) or nonexistent; writing to such memory, if allowed, can
16+ lead to memory corruption.
1617</p >
1718</overview >
1819<recommendation >
1920<p >
20- When checking for an out-of-range pointer, compare the pointer
21- value <code >p</code > against a known pointer value <code >p_max</code > representing
22- the highest allowable memory address. The <code >p_max</code > pointer should
23- point inside or just past the end of a defined memory region, such that
24- <code >p + a < = p_max</code >. Since we do not wish to evaluate <code >p + a</code >
25- (which may result in undefined behavior), we rewrite the inequality as
26- <code >p_max - p > a</code >.
27- </p >
21+ To check whether an index <code >a</code > is less than the length of an array,
22+ simply compare these two numbers as unsigned integers: <code >a < ARRAY_LENGTH</code >.
23+ If the length of the array is defined as the difference between two pointers
24+ <code >p</code > and <code >p_end</code >, write <code >a < p_end - p</code >.
25+ If a is <code >signed</code >, cast it to <code >unsigned</code >
26+ in order to guard against negative <code >a</code >. For example, write
27+ <code >(size_t)a < p_end - p</code >.</p >
2828</recommendation >
2929<example >
3030<p >
31- In the first example, a constant value is being added to a pointer and
32- then tested for "wrap around". Should the test fail, the developer
33- might assume that memory location <code >ptr + 0x12345678</code > is a
34- valid one for the program to use, even though it may be either
35- inaccessible (protected from the current process by the operating
36- system) or nonexistent. Furthermore, it may be impossible to tell when
37- the test succeeds, since pointer overflow has undefined behavior.
31+ In the first example, an index <code >a</code >is being added to a pointer <code >p</code >
32+ to an array with elements of type <code >T</code >. Since we are not provided a
33+ separate pointer pointing to the end of the array, we fall back
34+ on a check for address "wrap-around" to see if <code >p + a</code > points at
35+ valid memory. This scheme does not work, unfortunately, since the
36+ value of <code >p + a</code > is undefined if it points at invalid memory (for
37+ example, outside our array). Even if <code >p + a</code > were to point to
38+ some accessible memory location, it would almost certainly lie
39+ <i >outside</i > the bounds of the array.
3840</p >
3941<sample src =" PointerOverflowCheck-bad.cpp" />
4042<p >
4143The next example shows how to properly check for an out-of-range pointer.
4244In order to do so, we need to obtain the value <code >ptr_end</code >
43- representing the highest allowable memory address. In this case,
44- the address lies just beyond the end of an array.
45+ representing the end of the array (or the address immediately past
46+ the end). We can then express the condition <code >p + a < p_end</code > as a
47+ difference of two pointers, even if <code >p + a</code > happens to be undefined.
4548</p >
4649<sample src =" PointerOverflowCheck-good.cpp" />
4750</example >
0 commit comments