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

Skip to content

Commit 7dbb191

Browse files
committed
C++: Improve query precision
1 parent cfb839a commit 7dbb191

3 files changed

Lines changed: 43 additions & 6 deletions

File tree

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,32 @@ int getEffectiveMulOperands(MulExpr me) {
6464
)
6565
}
6666

67+
class LeafExpr extends Expr {
68+
LeafExpr() { not this instanceof BinaryOperation }
69+
}
70+
71+
/**
72+
* Gets the size of the largest type (in bytes) of an non-literal
73+
* operand to a binary operation. For example, for
74+
* ```
75+
* unsigned char a; short b;
76+
* (a + 1) * b;
77+
* ```
78+
* the result is 2 (i.e., the size of a `short`)
79+
*/
80+
int widenedFromLiteralFromSize(Expr e) {
81+
exists(Literal lit |
82+
lit = e.(BinaryOperation).getAnOperand+() and
83+
result = max(LeafExpr other |
84+
other = e.(BinaryOperation).getAnOperand+() and
85+
not other instanceof Literal
86+
|
87+
other.getType().getSize()
88+
) and
89+
result < lit.getType().getSize()
90+
)
91+
}
92+
6793
from MulExpr me, Type t1, Type t2
6894
where
6995
t1 = me.getType().getUnderlyingType() and
@@ -101,6 +127,20 @@ where
101127
e = other.(BinaryOperation).getAnOperand*()
102128
) and
103129
e.(Literal).getType().getSize() = t2.getSize()
130+
) and
131+
// exclude cases where the operands to the multiplication were
132+
// small, but widened due to a literal in a subexpression.
133+
// For instance, if the multiplication is
134+
// ```
135+
// int c = (a + 1) * (b + 1)
136+
// ```
137+
// where a and b are both unsigned chars. In this case the maximum
138+
// value of c will be 256 * 256, even though the arguments to the
139+
// multiplication are both typed as int.
140+
not exists(Expr e1, Expr e2 |
141+
e1 = me.getLeftOperand() and
142+
e2 = me.getRightOperand() and
143+
widenedFromLiteralFromSize(e1) + widenedFromLiteralFromSize(e2) < t1.getSize()
104144
)
105145
select me,
106146
"Multiplication result may overflow '" + me.getType().toString() + "' before it is converted to '"

cpp/ql/test/query-tests/Likely Bugs/Arithmetic/IntMultToLong/IntMultToLong.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ size_t three_chars(unsigned char a, unsigned char b, unsigned char c) {
9595

9696
void g(unsigned char a, unsigned char b, unsigned char b2, int c) {
9797
unsigned long d, e, f, g, h;
98-
d = (a + 1) * (b + 1); // GOOD [FALSE POSITIVE]
98+
d = (a + 1) * (b + 1); // GOOD
9999
e = (c + 1) * (b + 1); // BAD
100-
h = (a + 1) * (b + 1) * (b2 + 1); // GOOD [FALSE POSITIVE]
100+
h = (a + 1) * (b + 1) * (b2 + 1); // GOOD
101101

102-
f = (a + (a + 1)) * (b + 1); // GOOD [FALSE POSITIVE]
102+
f = (a + (a + 1)) * (b + 1); // GOOD
103103
g = (c + (a + 1)) * (b + 1); // BAD
104104
}

cpp/ql/test/query-tests/Likely Bugs/Arithmetic/IntMultToLong/IntMultToLong.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,5 @@
77
| IntMultToLong.c:61:23:61:33 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'long long'. |
88
| IntMultToLong.c:63:23:63:40 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'long long'. |
99
| IntMultToLong.c:75:9:75:13 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'size_t'. |
10-
| IntMultToLong.c:98:9:98:25 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |
1110
| IntMultToLong.c:99:9:99:25 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |
12-
| IntMultToLong.c:100:9:100:36 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |
13-
| IntMultToLong.c:102:9:102:31 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |
1411
| IntMultToLong.c:103:9:103:31 | ... * ... | Multiplication result may overflow 'int' before it is converted to 'unsigned long'. |

0 commit comments

Comments
 (0)