Skip to content

Commit 54253bc

Browse files
committed
C++: Resurrect underflow detection, but only on unsigned types.
1 parent 417edab commit 54253bc

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,19 @@ private class RandS extends RandomFunction {
7272
override FunctionOutput getFunctionOutput() { result.isParameterDeref(0) }
7373
}
7474

75-
predicate missingGuard(VariableAccess va) {
76-
exists(Operation op | op.getAnOperand() = va | missingGuardAgainstOverflow(op, va))
75+
predicate missingGuard(VariableAccess va, string effect) {
76+
exists(Operation op | op.getAnOperand() = va |
77+
// underflow - random numbers are usually non-negative, so underflow is
78+
// only likely if the type is unsigned. Multiplication is also unlikely to
79+
// cause underflow of a non-negative number.
80+
missingGuardAgainstUnderflow(op, va) and
81+
effect = "underflow" and
82+
op.getUnspecifiedType().(IntegralType).isUnsigned() and
83+
not op instanceof MulExpr
84+
or
85+
// overflow
86+
missingGuardAgainstOverflow(op, va) and effect = "overflow"
87+
)
7788
}
7889

7990
class UncontrolledArithConfiguration extends TaintTracking::Configuration {
@@ -91,7 +102,7 @@ class UncontrolledArithConfiguration extends TaintTracking::Configuration {
91102
)
92103
}
93104

94-
override predicate isSink(DataFlow::Node sink) { missingGuard(sink.asExpr()) }
105+
override predicate isSink(DataFlow::Node sink) { missingGuard(sink.asExpr(), _) }
95106

96107
override predicate isSanitizer(DataFlow::Node node) {
97108
bounded(node.asExpr())
@@ -115,11 +126,11 @@ Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgu
115126

116127
from
117128
UncontrolledArithConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
118-
VariableAccess va
129+
VariableAccess va, string effect
119130
where
120131
config.hasFlowPath(source, sink) and
121132
sink.getNode().asExpr() = va and
122-
missingGuard(va)
133+
missingGuard(va, effect)
123134
select sink.getNode(), source, sink,
124-
"$@ flows to here and is used in arithmetic, potentially causing an overflow.",
135+
"$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".",
125136
getExpr(source.getNode()), "Uncontrolled value"

cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/ArithmeticUncontrolled.expected

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ edges
88
| test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r |
99
| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r |
1010
| test.c:125:13:125:16 | call to rand | test.c:127:9:127:9 | r |
11+
| test.c:148:22:148:25 | call to rand | test.c:150:9:150:9 | r |
12+
| test.c:148:22:148:27 | (unsigned int)... | test.c:150:9:150:9 | r |
1113
| test.cpp:8:9:8:12 | Store | test.cpp:24:11:24:18 | call to get_rand |
1214
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
1315
| test.cpp:13:2:13:15 | Chi [[]] | test.cpp:30:13:30:14 | get_rand2 output argument [[]] |
@@ -41,6 +43,9 @@ nodes
4143
| test.c:100:5:100:5 | r | semmle.label | r |
4244
| test.c:125:13:125:16 | call to rand | semmle.label | call to rand |
4345
| test.c:127:9:127:9 | r | semmle.label | r |
46+
| test.c:148:22:148:25 | call to rand | semmle.label | call to rand |
47+
| test.c:148:22:148:27 | (unsigned int)... | semmle.label | (unsigned int)... |
48+
| test.c:150:9:150:9 | r | semmle.label | r |
4449
| test.cpp:8:9:8:12 | Store | semmle.label | Store |
4550
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
4651
| test.cpp:13:2:13:15 | Chi [[]] | semmle.label | Chi [[]] |
@@ -74,6 +79,8 @@ nodes
7479
| test.c:83:9:83:9 | r | test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:81:23:81:26 | call to rand | Uncontrolled value |
7580
| test.c:100:5:100:5 | r | test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value |
7681
| test.c:127:9:127:9 | r | test.c:125:13:125:16 | call to rand | test.c:127:9:127:9 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:125:13:125:16 | call to rand | Uncontrolled value |
82+
| test.c:150:9:150:9 | r | test.c:148:22:148:25 | call to rand | test.c:150:9:150:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:148:22:148:25 | call to rand | Uncontrolled value |
83+
| test.c:150:9:150:9 | r | test.c:148:22:148:27 | (unsigned int)... | test.c:150:9:150:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:148:22:148:25 | call to rand | Uncontrolled value |
7784
| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value |
7885
| test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | Uncontrolled value |
7986
| test.cpp:37:7:37:7 | r | test.cpp:18:9:18:12 | call to rand | test.cpp:37:7:37:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | Uncontrolled value |

cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/uncontrolled/test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,6 @@ void moreTests() {
147147
{
148148
unsigned int r = rand();
149149

150-
r = r - 100; // BAD [NOT DETECTED]
150+
r = r - 100; // BAD
151151
}
152152
}

0 commit comments

Comments
 (0)