-
Notifications
You must be signed in to change notification settings - Fork 1.7k
C++: Speed up the cpp/unbounded-write
query for an upcoming change
#18485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,11 +73,42 @@ predicate isSink(DataFlow::Node sink, BufferWrite bw, boolean qualifier) { | |
unboundedWriteSource(sink.asDefiningArgument(), bw, qualifier) | ||
} | ||
|
||
/** | ||
* A configuration that specifies flow from a `FlowSource` to a relational | ||
* comparison. | ||
* | ||
* This configuration is used to speed up the barrier computations in Config. | ||
*/ | ||
module BarrierConfig implements DataFlow::ConfigSig { | ||
predicate isSource(DataFlow::Node source) { isSource(source, _) } | ||
|
||
predicate isSink(DataFlow::Node sink) { | ||
comparesEq(sink.asOperand(), _, _, true, _) or | ||
comparesLt(sink.asOperand(), _, _, true, _) | ||
} | ||
} | ||
|
||
module BarrierFlow = TaintTracking::Global<BarrierConfig>; | ||
|
||
import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon | ||
|
||
/** | ||
* Holds if `left` is a left operand of some relational comparison that may | ||
* depend on user input. | ||
*/ | ||
predicate interestingLessThanOrEqual(Operand left) { | ||
exists(DataFlowImplCommon::NodeEx node | | ||
node.asNode().asOperand() = left and | ||
BarrierFlow::Stages::Stage1::sinkNode(node, _) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So my understanding/guessing is that stage one does some cheap flow starting at sources to find sink that could be interesting, and we are using that capability to prune down barriers as well. Is this something that the data flow library could actually do itself? Prune down barriers in this way. Or could it be bad to do more generally? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is that the As an alternative we could've inlined |
||
) | ||
} | ||
|
||
predicate lessThanOrEqual(IRGuardCondition g, Expr e, boolean branch) { | ||
exists(Operand left | | ||
g.comparesLt(left, _, _, true, branch) or | ||
g.comparesEq(left, _, _, true, branch) | ||
| | ||
interestingLessThanOrEqual(left) and | ||
left.getDef().getUnconvertedResultExpression() = e | ||
) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we want this predicate and the one below, given that they just forward arguments to
compares_eq
andcompares_lt
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The idea is that the fanout from
g
tog.comparesLt(...)
is quite large on certain repositories, so we want to create a way to compute a version ofcomparesLt
that can be used to prune the set of guards we want to look at early (in theinterestingLessThanOrEqual
predicate below).So the important part is that there's no
GuardCondition
as a column to this predicate (as that is what's giving the large fan-out). We can include theValueNumber
(i.e., the first column fromcompares_lt
) that is currently omitted from this predicate, but since it wasn't needed for the pruning inUnboundedWrite
I decided to leave it out to not expose that implementation detail.