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

Skip to content

Commit 3e1fd4a

Browse files
committed
[CPP-434] Add table of constructs to Qhelp. Rewrite examples section.
1 parent 1500148 commit 3e1fd4a

5 files changed

Lines changed: 110 additions & 27 deletions

File tree

change-notes/1.23/analysis-cpp.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
99
| **Query** | **Tags** | **Purpose** |
1010
|-----------------------------|-----------|--------------------------------------------------------------------|
1111
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). |
12-
| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which is undefined behavior. Example: `a + b < a`. |
12+
| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which has undefined behavior. Example: `a + b < a`. |
1313

1414
## Changes to existing queries
1515

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
bool bar(unsigned short n1, unsigned short delta) {
22
// NB: Comparison is always false
3-
return n1 + delta < n1; // GOOD
3+
return n1 + delta < n1; // GOOD (but misleading)
44
}
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
bool baf(unsigned short n1, unsigned short delta) {
2-
return (unsigned short)(n1 + delta) < n1; // GOOD
1+
#include <limits.h>
2+
bool foo(int n1, unsigned short delta) {
3+
return n1 > INT_MAX - delta; // GOOD
34
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
bool baz(int n1, int delta) {
2-
return (unsigned)n1 + delta < n1; // GOOD
1+
bool bar(unsigned short n1, unsigned short delta) {
2+
return (unsigned short)(n1 + delta) < n1; // GOOD
33
}

cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp

Lines changed: 103 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
<qhelp>
55
<overview>
66
<p>
7-
When checking for integer overflow, one often writes tests like
7+
When checking for integer overflow, you may often write tests like
88
<code>a + b &lt; a</code>. This works fine if <code>a</code> or
99
<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 overflows have undefined
10+
will cause the value to simply "wrap around." However, using
11+
<i>signed</i> integers is problematic because signed overflow has undefined
1212
behavior according to the C and C++ standards. If the addition overflows
1313
and has an undefined result, the comparison will likewise be undefined;
1414
it may produce an unintended result, or may be deleted entirely by an
@@ -17,10 +17,89 @@ optimizing compiler.
1717
</overview>
1818
<recommendation>
1919
<p>
20-
When checking for overflow by adding two values, first make sure that <code>a</code>
21-
or <code>b</code> are (converted into) unsigned values, unless it is
22-
certain that the signed addition cannot overflow.
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+
25+
The table below lists various expressions where signed overflow may
26+
occur, along with proposed rewritings. It should not be
27+
considered as exhaustive.
2328
</p>
29+
<table>
30+
<tr>
31+
<th>Original Construct</th>
32+
<th>Alternate Construct(s)</th>
33+
<th>Notes</th>
34+
</tr>
35+
<tr>
36+
<td><tt><table>
37+
<tr>
38+
<td>unsigned short i, delta;</td>
39+
</tr><tr>
40+
<td>i + delta &lt; i</td>
41+
</tr>
42+
</table></tt></td>
43+
<td><tt><table>
44+
<tr>
45+
<td>unsigned short i, delta;</td>
46+
</tr><tr>
47+
<td>(unsigned short)(i + delta)&nbsp;&lt;&nbsp;i</td>
48+
</tr>
49+
</table></tt></td>
50+
<td><tt>i + delta</tt>does not actually overflow due to <tt>int</tt> promotion</td>
51+
</tr>
52+
<tr>
53+
<td>&nbsp;</td>
54+
<td><tt><table>
55+
<tr>
56+
<td>unsigned short i, delta;</td>
57+
</tr><tr>
58+
<td>i > USHORT_MAX - delta</td>
59+
</tr>
60+
</table></tt></td>
61+
<td>Must include <tt>limits.h</tt> or <tt>climits</tt></td>
62+
</tr>
63+
<tr>
64+
<td><tt><table>
65+
<tr>
66+
<td>int i, delta;</td>
67+
</tr><tr>
68+
<td>i + delta &lt; i</td>
69+
</tr>
70+
</table></tt></td>
71+
<td><tt><table>
72+
<tr>
73+
<td>int i, delta;</td>
74+
</tr><tr>
75+
<td>i &gt; INT_MAX - delta</td>
76+
</tr>
77+
</table></tt></td>
78+
<td>Must include <tt>limits.h</tt> or <tt>climits</tt></td>
79+
</tr>
80+
<tr>
81+
<td>&nbsp;</td>
82+
<td><tt><table>
83+
<tr>
84+
<td>int i, delta;</td>
85+
</tr><tr>
86+
<td>(unsigned)i + delta &lt; i</td>
87+
</tr>
88+
</table></tt></td>
89+
<td>Change in program semantics</td>
90+
</tr>
91+
<tr>
92+
<td>&nbsp;</td>
93+
<td><tt><table>
94+
<tr>
95+
<td>unsigned int i, delta;</td>
96+
</tr><tr>
97+
<td>i + delta &lt; i</td>
98+
</tr>
99+
</table></tt></td>
100+
<td>Change in program semantics</td>
101+
</tr>
102+
</table>
24103
</recommendation>
25104
<example>
26105
<p>
@@ -34,6 +113,17 @@ result.
34113
</p>
35114
<sample src="SignedOverflowCheck-bad1.cpp" />
36115
<p>
116+
The following example builds upon the previous one. Instead of
117+
performing an addition (which could overflow), we have re-framed the
118+
solution so that a subtraction is used instead. Since <code>delta</code>
119+
is promoted to a <code>signed int</code> and <code>INT_MAX</code> denotes
120+
the largest possible positive value for an <code>signed int</code>,
121+
the expression <code>INT_MAX - delta</code> can never be less than zero
122+
or more than <code>INT_MAX</code>. Hence, any overflow and underflow
123+
are avoided.
124+
</p>
125+
<sample src="SignedOverflowCheck-good1.cpp" />
126+
<p>
37127
In the following example, even though both <code>n</code> and <code>delta</code>
38128
have been declared <code>unsigned short</code>, both are promoted to
39129
<code>signed int</code> prior to addition. Because we started out with the
@@ -45,26 +135,18 @@ hold true, which likely is not what the programmer intended. (see also the
45135
</p>
46136
<sample src="SignedOverflowCheck-bad2.cpp" />
47137
<p>
48-
The following example builds upon the previous one. Again, we have two
49-
<code>unsigned short</code> values getting promoted to a wider type, resulting
50-
in a comparison that always succeeds (since there is no overflow). To
51-
test whether we have an <code>unsigned short</code> overflow, we cast the
52-
left-hand side to it, causing the right-hand side to remain an <code>unsigned
53-
short</code> as well.
54-
</p>
55-
<sample src="SignedOverflowCheck-good1.cpp" />
56-
<p>
57-
In the next example, we have two <code>signed int</code> values that we
58-
wish to add together. Adding them "as-is" opens the possibility of
59-
a signed integer overflow, the results of which are undefined.
60-
By casting one of the operands to <code>unsigned</code>, the entire
61-
expression is evaluated using <code>unsigned</code>
62-
values, which is defined behavior per the C/C++ standard.
138+
The next example provides a solution to the previous one. Even though
139+
<code>i + delta</code> does not overflow, casting it to an
140+
<code>unsigned short</code> truncates the addition modulo 2^16,
141+
so that <code>unsigned short</code> "wrap around" may now be observed.
142+
Furthermore, since the left-hand side is now of type <code>unsigned short</code>,
143+
the right-hand side does not need to be promoted to a <code>signed int</code>.
63144
</p>
64145
<sample src="SignedOverflowCheck-good2.cpp" />
65146
</example>
66147
<references>
67148
<li><a href="http://c-faq.com/expr/preservingrules.html">comp.lang.c FAQ list · Question 3.19 (Preserving rules)</a></li>
68149
<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>
150+
<li>W. Dietz,∗ P. Li, J. Regehr, V. Adve. <a href="http://www.cs.utah.edu/~regehr/papers/overflow12.pdf">Understanding Integer Overflow in C/C++</a></li>
69151
</references>
70152
</qhelp>

0 commit comments

Comments
 (0)