Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -1160,12 +1160,19 @@ private module Cached {
/** Holds if `n` is a flow barrier of kind `kind`. */
cached
predicate barrierNode(Node n, string kind) {
exists(string model |
n.(FlowSummaryNode)
.getSummaryNode()
.(FlowSummaryImpl::Private::SourceOutputNode)
.isEntry(kind, model)
// getSourceElement().(FlowBarrier).isBarrier(_, kind, _, _)
exists(
FlowSummaryImpl::Public::BarrierElement b,
FlowSummaryImpl::Private::SummaryComponentStack stack
|
FlowSummaryImpl::Private::barrierSpec(b, stack, kind, _)
|
n = FlowSummaryImpl::StepsInput::getSourceNode(b, stack, false)
or
// For barriers like `Argument[0]` we want to target the pre-update node
n =
FlowSummaryImpl::StepsInput::getSourceNode(b, stack, true)
.(PostUpdateNode)
.getPreUpdateNode()
)
}

Expand Down
19 changes: 14 additions & 5 deletions rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ module Input implements InputSig<Location, RustDataFlow> {

private import Make<Location, RustDataFlow, Input> as Impl

private module StepsInput implements Impl::Private::StepsInputSig {
module StepsInput implements Impl::Private::StepsInputSig {
DataFlowCall getACall(Public::SummarizedCallable sc) { result.asCall().getStaticTarget() = sc }

/** Gets the argument of `source` described by `sc`, if any. */
Expand Down Expand Up @@ -171,18 +171,27 @@ private module StepsInput implements Impl::Private::StepsInputSig {
result.asCfgScope() = source.getEnclosingCfgScope()
}

RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) {
additional RustDataFlow::Node getSourceNode(
Input::SourceBase source, Impl::Private::SummaryComponentStack s, boolean isArgPostUpdate
) {
s.head() = Impl::Private::SummaryComponent::return(_) and
result.asExpr() = source.getCall()
result.asExpr() = source.getCall() and
isArgPostUpdate = false
or
exists(RustDataFlow::ArgumentPosition pos, Expr arg |
s.head() = Impl::Private::SummaryComponent::parameter(pos) and
arg = getSourceNodeArgument(source, s.tail().headOfSingleton()) and
result.asParameter() = getCallable(arg).getParam(pos.getPosition())
result.asParameter() = getCallable(arg).getParam(pos.getPosition()) and
isArgPostUpdate = false
)
or
result.(RustDataFlow::PostUpdateNode).getPreUpdateNode().asExpr() =
getSourceNodeArgument(source, s.headOfSingleton())
getSourceNodeArgument(source, s.headOfSingleton()) and
isArgPostUpdate = true
}

RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) {
result = getSourceNode(source, s, _)
}

RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
Expand Down
30 changes: 28 additions & 2 deletions shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,19 @@ module Make<
)
}

private predicate summarySpec(string spec) {
private predicate isRelevantBarrier(
BarrierElement e, string output, string kind, Provenance provenance, string model
) {
e.isBarrier(output, kind, provenance, model) and
(
provenance.isManual()
or
provenance.isGenerated() and
not exists(Provenance p | p.isManual() and e.isBarrier(_, kind, p, _))
)
}

private predicate flowSpec(string spec) {
exists(SummarizedCallable c |
c.propagatesFlow(spec, _, _, _, _, _)
or
Expand All @@ -745,10 +757,12 @@ module Make<
or
isRelevantSource(_, spec, _, _, _)
or
isRelevantBarrier(_, spec, _, _, _)
or
isRelevantSink(_, spec, _, _, _)
}

import AccessPathSyntax::AccessPath<summarySpec/1>
import AccessPathSyntax::AccessPath<flowSpec/1>

/** Holds if specification component `token` parses as parameter `pos`. */
predicate parseParam(AccessPathToken token, ArgumentPosition pos) {
Expand Down Expand Up @@ -1528,6 +1542,18 @@ module Make<
)
}

/**
* Holds if `barrier` is a relevant barrier element with output specification `outSpec`.
*/
predicate barrierSpec(
BarrierElement barrier, SummaryComponentStack outSpec, string kind, string model
) {
exists(string output |
isRelevantBarrier(barrier, output, kind, _, model) and
External::interpretSpec(output, outSpec)
)
}

signature module TypesInputSig {
/** Gets the type of content `c`. */
DataFlowType getContentType(ContentSet c);
Expand Down
Loading