Skip to content

Commit aa55b8e

Browse files
authored
Merge pull request #18485 from MathiasVP/speed-up-cpp-unbounded-write
C++: Speed up the `cpp/unbounded-write` query for an upcoming change
2 parents a2aefc9 + 2d44b33 commit aa55b8e

File tree

2 files changed

+53
-0
lines changed

2 files changed

+53
-0
lines changed

cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,3 +1453,25 @@ private module Cached {
14531453
}
14541454

14551455
private import Cached
1456+
1457+
/**
1458+
* Holds if `left < right + k` evaluates to `isLt` given that some guard
1459+
* evaluates to `value`.
1460+
*
1461+
* To find the specific guard that performs the comparison
1462+
* use `IRGuards.comparesLt`.
1463+
*/
1464+
predicate comparesLt(Operand left, Operand right, int k, boolean isLt, AbstractValue value) {
1465+
compares_lt(_, left, right, k, isLt, value)
1466+
}
1467+
1468+
/**
1469+
* Holds if `left = right + k` evaluates to `isLt` given that some guard
1470+
* evaluates to `value`.
1471+
*
1472+
* To find the specific guard that performs the comparison
1473+
* use `IRGuards.comparesEq`.
1474+
*/
1475+
predicate comparesEq(Operand left, Operand right, int k, boolean isLt, AbstractValue value) {
1476+
compares_eq(_, left, right, k, isLt, value)
1477+
}

cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,42 @@ predicate isSink(DataFlow::Node sink, BufferWrite bw, boolean qualifier) {
7373
unboundedWriteSource(sink.asDefiningArgument(), bw, qualifier)
7474
}
7575

76+
/**
77+
* A configuration that specifies flow from a `FlowSource` to a relational
78+
* comparison.
79+
*
80+
* This configuration is used to speed up the barrier computations in Config.
81+
*/
82+
module BarrierConfig implements DataFlow::ConfigSig {
83+
predicate isSource(DataFlow::Node source) { isSource(source, _) }
84+
85+
predicate isSink(DataFlow::Node sink) {
86+
comparesEq(sink.asOperand(), _, _, true, _) or
87+
comparesLt(sink.asOperand(), _, _, true, _)
88+
}
89+
}
90+
91+
module BarrierFlow = TaintTracking::Global<BarrierConfig>;
92+
93+
import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
94+
95+
/**
96+
* Holds if `left` is a left operand of some relational comparison that may
97+
* depend on user input.
98+
*/
99+
predicate interestingLessThanOrEqual(Operand left) {
100+
exists(DataFlowImplCommon::NodeEx node |
101+
node.asNode().asOperand() = left and
102+
BarrierFlow::Stages::Stage1::sinkNode(node, _)
103+
)
104+
}
105+
76106
predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) {
77107
exists(Operand left |
78108
g.comparesLt(left, _, _, true, branch) or
79109
g.comparesEq(left, _, _, true, branch)
80110
|
111+
interestingLessThanOrEqual(left) and
81112
left.getDef().getUnconvertedResultExpression() = e
82113
)
83114
}

0 commit comments

Comments
 (0)