|
| 1 | +<!DOCTYPE qhelp PUBLIC |
| 2 | + "-//Semmle//qhelp//EN" |
| 3 | + "qhelp.dtd"> |
| 4 | +<qhelp> |
| 5 | +<overview> |
| 6 | +<p> |
| 7 | +When checking for integer overflow, you may often write tests like |
| 8 | +<code>a + b < a</code>. This works fine if <code>a</code> or |
| 9 | +<code>b</code> are unsigned integers, since any overflow in the addition |
| 10 | +will cause the value to simply "wrap around." However, using |
| 11 | +<i>signed</i> integers is problematic because signed overflow has undefined |
| 12 | +behavior according to the C and C++ standards. If the addition overflows |
| 13 | +and has an undefined result, the comparison will likewise be undefined; |
| 14 | +it may produce an unintended result, or may be deleted entirely by an |
| 15 | +optimizing compiler. |
| 16 | +</p> |
| 17 | +</overview> |
| 18 | +<recommendation> |
| 19 | +<p> |
| 20 | +Solutions to this problem can be thought of as falling into one of two |
| 21 | +categories: (1) rewrite the signed expression so that overflow cannot occur |
| 22 | +but the signedness remains, or (2) rewrite (or cast) the signed expression |
| 23 | +into unsigned form. |
| 24 | +</p> |
| 25 | + |
| 26 | +<p> |
| 27 | +Below we list examples of expressions where signed overflow may |
| 28 | +occur, along with proposed solutions. The list should not be |
| 29 | +considered exhaustive. |
| 30 | +</p> |
| 31 | + |
| 32 | +<p> |
| 33 | +Given <code>unsigned short i, delta</code> and <code>i + delta < i</code>, |
| 34 | +it is possible to rewrite it as <code>(unsigned short)(i + delta) < i</code>. |
| 35 | +Note that <code>i + delta</code>does not actually overflow, due to <code>int</code> promotion |
| 36 | +</p> |
| 37 | + |
| 38 | +<p> |
| 39 | +Given <code>unsigned short i, delta</code> and <code>i + delta < i</code>, |
| 40 | +it is also possible to rewrite it as <code>USHORT_MAX - delta</code>. It must be true |
| 41 | +that <code>delta > 0</code> and the <code>limits.h</code> or <code>climits</code> |
| 42 | +header has been included. |
| 43 | +</p> |
| 44 | + |
| 45 | +<p> |
| 46 | +Given <code>int i, delta</code> and <code>i + delta < i</code>, |
| 47 | +it is possible to rewrite it as <code>INT_MAX - delta</code>. It must be true |
| 48 | +that <code>delta > 0</code> and the <code>limits.h</code> or <code>climits</code> |
| 49 | +header has been included. |
| 50 | +</p> |
| 51 | + |
| 52 | +<p> |
| 53 | +Given <code>int i, delta</code> and <code>i + delta < i</code>, |
| 54 | +it is also possible to rewrite it as <code>(unsigned)i + delta < i</code>. |
| 55 | +Note that program semantics are affected by this change. |
| 56 | +</p> |
| 57 | + |
| 58 | +<p> |
| 59 | +Given <code>int i, delta</code> and <code>i + delta < i</code>, |
| 60 | +it is also possible to rewrite it as <code>unsigned int i, delta</code> and |
| 61 | +<code>i + delta < i</code>. Note that program semantics are |
| 62 | +affected by this change. |
| 63 | +</p> |
| 64 | +</recommendation> |
| 65 | + |
| 66 | +<example> |
| 67 | +<p> |
| 68 | +In the following example, even though <code>delta</code> has been declared |
| 69 | +<code>unsigned short</code>, C/C++ type promotion rules require that its |
| 70 | +type is promoted to the larger type used in the addition and comparison, |
| 71 | +namely a <code>signed int</code>. Addition is performed on |
| 72 | +signed integers, and may have undefined behavior if an overflow occurs. |
| 73 | +As a result, the entire (comparison) expression may also have an undefined |
| 74 | +result. |
| 75 | +</p> |
| 76 | +<sample src="SignedOverflowCheck-bad1.cpp" /> |
| 77 | +<p> |
| 78 | +The following example builds upon the previous one. Instead of |
| 79 | +performing an addition (which could overflow), we have re-framed the |
| 80 | +solution so that a subtraction is used instead. Since <code>delta</code> |
| 81 | +is promoted to a <code>signed int</code> and <code>INT_MAX</code> denotes |
| 82 | +the largest possible positive value for an <code>signed int</code>, |
| 83 | +the expression <code>INT_MAX - delta</code> can never be less than zero |
| 84 | +or more than <code>INT_MAX</code>. Hence, any overflow and underflow |
| 85 | +are avoided. |
| 86 | +</p> |
| 87 | +<sample src="SignedOverflowCheck-good1.cpp" /> |
| 88 | +<p> |
| 89 | +In the following example, even though both <code>n</code> and <code>delta</code> |
| 90 | +have been declared <code>unsigned short</code>, both are promoted to |
| 91 | +<code>signed int</code> prior to addition. Because we started out with the |
| 92 | +narrower <code>short</code> type, the addition is guaranteed not to overflow |
| 93 | +and is therefore defined. But the fact that <code>n1 + delta</code> never |
| 94 | +overflows means that the condition <code>n1 + delta < n1</code> will never |
| 95 | +hold true, which likely is not what the programmer intended. (see also the |
| 96 | +<code>cpp/bad-addition-overflow-check</code> query). |
| 97 | +</p> |
| 98 | +<sample src="SignedOverflowCheck-bad2.cpp" /> |
| 99 | +<p> |
| 100 | +The next example provides a solution to the previous one. Even though |
| 101 | +<code>i + delta</code> does not overflow, casting it to an |
| 102 | +<code>unsigned short</code> truncates the addition modulo 2^16, |
| 103 | +so that <code>unsigned short</code> "wrap around" may now be observed. |
| 104 | +Furthermore, since the left-hand side is now of type <code>unsigned short</code>, |
| 105 | +the right-hand side does not need to be promoted to a <code>signed int</code>. |
| 106 | +</p> |
| 107 | + |
| 108 | +<sample src="SignedOverflowCheck-good2.cpp" /> |
| 109 | +</example> |
| 110 | +<references> |
| 111 | +<li><a href="http://c-faq.com/expr/preservingrules.html">comp.lang.c FAQ list · Question 3.19 (Preserving rules)</a></li> |
| 112 | +<li><a href="https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data">INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data</a></li> |
| 113 | +<li>W. Dietz, P. Li, J. Regehr, V. Adve. <a href="https://www.cs.utah.edu/~regehr/papers/overflow12.pdf">Understanding Integer Overflow in C/C++</a></li> |
| 114 | +</references> |
| 115 | +</qhelp> |
0 commit comments