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

Skip to content

Commit ad5aa18

Browse files
committed
[CPP-434] When analyzing overflow, discard any explicit casts.
Use the simple range analysis library to detect which additions may in fact overflow.
1 parent 06f63c5 commit ad5aa18

4 files changed

Lines changed: 13 additions & 25 deletions

File tree

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

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,15 @@
1212
*/
1313

1414
import cpp
15-
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16-
17-
private predicate isSignedWithoutUnsignedCast(Expr e) {
18-
e.getType().getUnspecifiedType().(IntegralType).isSigned()
19-
/*
20-
* and
21-
* not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned()
22-
*/
23-
24-
}
15+
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16+
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
2517

2618
from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2
2719
where
2820
ro.getAnOperand() = add and
2921
add.getAnOperand() = va1 and
3022
ro.getAnOperand() = va2 and
3123
globalValueNumber(va1) = globalValueNumber(va2) and
32-
isSignedWithoutUnsignedCast(add)
24+
add.getType().getUnspecifiedType().(IntegralType).isSigned() and
25+
exprMightOverflowPositively(add)
3326
select ro, "Testing for signed overflow may produce undefined results."

cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ bool shortShort1(unsigned short n1, unsigned short delta) {
3232
// clang 8.0.0 -O2: deleted
3333
// gcc 9.2 -O2: deleted
3434
// msvc 19.22 /O2: not deleted
35-
return n1 + delta < n1; // BAD: will always be false
35+
return n1 + delta < n1; // GOOD: always false, but will never overflow
3636
}
3737

3838
bool shortShort2(unsigned short n1, unsigned short delta) {
@@ -96,28 +96,28 @@ int checkOverflow4(unsigned int ioff, C c) {
9696

9797
int overflow12(int n) {
9898
// not deleted by gcc or clang
99-
return (n + 32 <= (unsigned)n? -1: 1); // BAD
99+
return (n + 32 <= (unsigned)n? -1: 1); // BAD: n + 32 can overflow
100100
}
101101

102102
bool multipleCasts(char x) {
103103
// clang 9.0.0 -O2: deleted
104104
// gcc 9.2 -O2: deleted
105105
// msvc 19.22 /O2: deleted
106-
return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // BAD
106+
return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // GOOD: cannot overflow
107107
}
108108

109109
bool multipleCasts2(char x) {
110110
// clang 9.0.0 -O2: not deleted
111111
// gcc 9.2 -O2: not deleted
112112
// msvc 19.22 /O2: not deleted
113-
return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // BAD
113+
return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD: cannot overflow
114114
}
115115

116116
int does_it_overflow(int n1, unsigned short delta) {
117-
return n1 + (unsigned)delta < n1; // GOOD
117+
return n1 + (unsigned)delta < n1; // GOOD: everything converted to unsigned
118118
}
119119

120120
int overflow12b(int n) {
121121
// not deleted by gcc or clang
122-
return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD
122+
return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD: n + 32 may overflow
123123
}
Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. |
22
| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. |
3-
| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. |
4-
| SignedOverflowCheck.cpp:42:9:42:41 | ... < ... | Testing for signed overflow may produce undefined results. |
53
| SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. |
6-
| SignedOverflowCheck.cpp:106:12:106:62 | ... < ... | Testing for signed overflow may produce undefined results. |
7-
| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Testing for signed overflow may produce undefined results. |
8-
| test.cpp:3:11:3:19 | ... < ... | Testing for signed overflow may produce undefined results. |
9-
| test.cpp:8:11:8:37 | ... < ... | Testing for signed overflow may produce undefined results. |
4+
| SignedOverflowCheck.cpp:122:10:122:42 | ... <= ... | Testing for signed overflow may produce undefined results. |

cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Test for BadAdditionOverflowCheck.
22
bool checkOverflow1(unsigned short a, unsigned short b) {
3-
return (a + b < a); // BAD: a + b is automatically promoted to int.
3+
return (a + b < a); // BAD: comparison always false (due to promotion).
44
}
55

66
// Test for BadAdditionOverflowCheck.
77
bool checkOverflow2(unsigned short a, unsigned short b) {
8-
return ((unsigned short)(a + b) < a); // BAD: a + b overflow undefined
8+
return ((unsigned short)(a + b) < a); // GOOD
99
}
1010

1111
// Test for PointlessSelfComparison.

0 commit comments

Comments
 (0)