Skip to content

Commit 1500148

Browse files
committed
[CPP-434] Clarify Qhelp.
1 parent 6ee3d7d commit 1500148

3 files changed

Lines changed: 30 additions & 24 deletions

File tree

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
bool baf(unsigned short n1, unsigned short delta) {
2-
return n1 + (unsigned)delta < n1; // GOOD
2+
return (unsigned short)(n1 + delta) < n1; // GOOD
33
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
bool baz(int n1, unsigned int delta) {
2-
return n1 + delta < n1; // GOOD
1+
bool baz(int n1, int delta) {
2+
return (unsigned)n1 + delta < n1; // GOOD
33
}

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

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,33 @@
44
<qhelp>
55
<overview>
66
<p>
7-
Testing for signed integer overflow by adding a
8-
two signed values together and then comparing the result to one
9-
of the values is ill-formed since the overflow check is undefined.
10-
The comparison may produce an unintended result, or may be deleted
11-
by the compiler entirely.
7+
When checking for integer overflow, one often writes tests like
8+
<code>a + b &lt; 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 overflows have 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.
1216
</p>
1317
</overview>
1418
<recommendation>
1519
<p>
16-
When checking for overflow, make sure that <code>unsigned</code> values are used.
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.
1723
</p>
1824
</recommendation>
1925
<example>
2026
<p>
2127
In the following example, even though <code>delta</code> has been declared
2228
<code>unsigned short</code>, C/C++ type promotion rules require that its
2329
type is promoted to the larger type used in the addition and comparison,
24-
namely a <code>signed int</code>. As a result, the entire expression is
25-
evaluated using <code>signed</code> integers and may overflow, and hence
26-
is undefined.
30+
namely a <code>signed int</code>. Addition is performed on
31+
signed integers, and may have undefined behavior if an overflow occurs.
32+
As a result, the entire (comparison) expression may also have an undefined
33+
result.
2734
</p>
2835
<sample src="SignedOverflowCheck-bad1.cpp" />
2936
<p>
@@ -39,21 +46,20 @@ hold true, which likely is not what the programmer intended. (see also the
3946
<sample src="SignedOverflowCheck-bad2.cpp" />
4047
<p>
4148
The following example builds upon the previous one. Again, we have two
42-
<code>unsigned short</code> values getting promoted to a wider type. However,
43-
since <code>delta</code> is explicitly cast to an <code>unsigned</code> type,
44-
<code>n1</code> (on both sides of the comparison) is promoted to
45-
<code>unsigned int</code> as well. Since we are now operating on
46-
<code>unsigned</code> values, the overflow check is defined and supported by
47-
standard C/C++.
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.
4854
</p>
4955
<sample src="SignedOverflowCheck-good1.cpp" />
5056
<p>
51-
In the next example, a value of type <code>signed int</code> is
52-
added to a value of type <code>unsigned int</code>. Because
53-
the types are of the same size, C/C++ conversion rules dictate that
54-
<code>unsigned int</code> is chosen as the overall type of the addition
55-
operation. The entire expression is evaluated using <code>unsigned</code>
56-
values, which is allowed and defined behavior per the C/C++ standard.
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.
5763
</p>
5864
<sample src="SignedOverflowCheck-good2.cpp" />
5965
</example>

0 commit comments

Comments
 (0)