Skip to content

Commit 717a846

Browse files
committed
C++: Support for access path at sources and sinks.
1 parent 7668499 commit 717a846

5 files changed

Lines changed: 128 additions & 10 deletions

File tree

cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ private import new.DataFlow
115115
private import semmle.code.cpp.controlflow.IRGuards
116116
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate as Private
117117
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
118+
private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes as Nodes
118119
private import internal.FlowSummaryImpl
119120
private import internal.FlowSummaryImpl::Public
120121
private import internal.FlowSummaryImpl::Private
@@ -952,9 +953,7 @@ private module Cached {
952953
*/
953954
cached
954955
predicate sourceNode(DataFlow::Node node, string kind, string model) {
955-
exists(SourceSinkInterpretationInput::InterpretNode n |
956-
isSourceNode(n, kind, model) and n.asNode() = node
957-
)
956+
node.(Nodes::FlowSummaryNode).isSource(kind, model)
958957
}
959958

960959
/**

cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 82 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,32 @@ private import semmle.code.cpp.dataflow.ExternalFlow
1313
private import semmle.code.cpp.ir.IR
1414

1515
module Input implements InputSig<Location, DataFlowImplSpecific::CppDataFlow> {
16-
private import codeql.util.Void
17-
1816
class SummarizedCallableBase = Function;
1917

20-
class SourceBase = Void;
18+
abstract private class SourceSinkBase extends Element {
19+
/** Gets the call associated with this element, if any. */
20+
CallInstruction getCall() { none() }
21+
22+
/** Gets the function associated with this element, if any. */
23+
Function getFunction() { none() }
24+
25+
/** Gets the enclosing function of this element. */
26+
abstract Declaration getEnclosingFunction();
27+
}
28+
29+
abstract class SourceBase extends SourceSinkBase { }
30+
31+
abstract class SinkBase extends SourceSinkBase { }
32+
33+
private class SourceSinkCall extends SourceBase, SinkBase instanceof Call {
34+
CallInstruction call;
35+
36+
SourceSinkCall() { call.getUnconvertedResultExpression() = this }
2137

22-
class SinkBase = Void;
38+
final override CallInstruction getCall() { result = call }
39+
40+
final override Declaration getEnclosingFunction() { result = Call.super.getEnclosingFunction() }
41+
}
2342

2443
class FlowSummaryCallBase = CallInstruction;
2544

@@ -149,9 +168,46 @@ private module StepsInput implements Impl::Private::StepsInputSig {
149168
)
150169
}
151170

152-
DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) { none() }
171+
DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) {
172+
result.asSourceCallable() = source.getEnclosingFunction()
173+
}
174+
175+
private ArgumentNode getSourceNodeArgument(
176+
Input::SourceBase source, Impl::Private::SummaryComponent sc
177+
) {
178+
exists(Position pos, DataFlowCall call |
179+
sc = Impl::Private::SummaryComponent::argument(pos) and
180+
source.getCall() = call.asCallInstruction() and
181+
result.argumentOf(call, pos)
182+
)
183+
}
153184

154-
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { none() }
185+
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) {
186+
exists(ReturnKind rk, DataFlowCall call |
187+
s.head() = Impl::Private::SummaryComponent::return(rk) and
188+
source.getCall() = call.asCallInstruction() and
189+
result = getAnOutNode(call, rk)
190+
)
191+
or
192+
exists(Position pos, DataFlowCallable callable |
193+
s.head() = Impl::Private::SummaryComponent::parameter(pos) and
194+
result.(ParameterNode).isParameterOf(callable, pos)
195+
|
196+
exists(ArgumentNode arg, DataFlowCall call |
197+
arg = getSourceNodeArgument(source, s.tail().headOfSingleton()) and
198+
arg.argumentOf(call, pos) and
199+
callable = call.getStaticCallTarget()
200+
)
201+
or
202+
source.getFunction() = callable.asSourceCallable()
203+
)
204+
or
205+
exists(Position pos |
206+
s.head() = Impl::Private::SummaryComponent::argument(pos) and
207+
result.(PostUpdateNode).getPreUpdateNode() =
208+
getSourceNodeArgument(source, s.headOfSingleton())
209+
)
210+
}
155211

156212
Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) { none() }
157213
}
@@ -310,3 +366,23 @@ module Private {
310366
}
311367

312368
module Public = Impl::Public;
369+
370+
private class SourceModelCall extends Public::SourceElement instanceof Call {
371+
private string namespace;
372+
private string type;
373+
private boolean subtypes;
374+
private string name;
375+
private string signature;
376+
private string ext;
377+
378+
SourceModelCall() {
379+
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) and
380+
this.getTarget() = interpretElement(namespace, type, subtypes, name, signature, ext)
381+
}
382+
383+
override predicate isSource(
384+
string output, string kind, Public::Provenance provenance, string model
385+
) {
386+
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model)
387+
}
388+
}

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1534,11 +1534,46 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
15341534
result = this.getSummaryNode().getSummarizedCallable()
15351535
}
15361536

1537+
/** Gets the source element that this node belongs to, if any. */
1538+
FlowSummaryImpl::Public::SourceElement getSourceElement() {
1539+
result = this.getSummaryNode().getSourceElement()
1540+
}
1541+
1542+
/** Gets the sink element that this node belongs to, if any. */
1543+
FlowSummaryImpl::Public::SinkElement getSinkElement() {
1544+
result = this.getSummaryNode().getSinkElement()
1545+
}
1546+
1547+
/** Holds if this node is a source node of kind `kind`. */
1548+
predicate isSource(string kind, string model) {
1549+
this.getSummaryNode().(FlowSummaryImpl::Private::SourceOutputNode).isEntry(kind, model)
1550+
}
1551+
1552+
/** Holds if this node is a sink node of kind `kind`. */
1553+
predicate isSink(string kind, string model) {
1554+
this.getSummaryNode().(FlowSummaryImpl::Private::SinkInputNode).isExit(kind, model)
1555+
}
1556+
1557+
/**
1558+
* Gets the enclosing callable. For a `FlowSummaryNode` this is always the
1559+
* summarized function this node is part of.
1560+
*/
15371561
override DataFlowCallable getEnclosingCallable() {
15381562
result = FlowSummaryImpl::Private::getEnclosingCallable(this.getSummaryNode())
1563+
or
1564+
// TODO: This could actually be done by the shared library.
1565+
result.asSourceCallable() = this.getSourceElement().getEnclosingFunction()
1566+
or
1567+
result.asSourceCallable() = this.getSinkElement().getEnclosingFunction()
15391568
}
15401569

1541-
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }
1570+
override Location getLocationImpl() {
1571+
result = this.getSummarizedCallable().getLocation()
1572+
or
1573+
result = this.getSourceElement().getLocation()
1574+
or
1575+
result = this.getSinkElement().getLocation()
1576+
}
15421577

15431578
override string toStringImpl() { result = this.getSummaryNode().toString() }
15441579
}

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ private module Cached {
121121
// models-as-data summarized flow
122122
FlowSummaryImpl::Private::Steps::summaryJumpStep(n1.(FlowSummaryNode).getSummaryNode(),
123123
n2.(FlowSummaryNode).getSummaryNode())
124+
or
125+
FlowSummaryImpl::Private::Steps::sourceJumpStep(n1.(FlowSummaryNode).getSummaryNode(), n2)
124126
}
125127

126128
/**

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ private module Cached {
160160
// models-as-data summarized flow
161161
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom,
162162
nodeTo.(FlowSummaryNode).getSummaryNode(), true, model)
163+
or
164+
FlowSummaryImpl::Private::Steps::sourceLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
165+
nodeTo, model)
166+
or
167+
FlowSummaryImpl::Private::Steps::sinkLocalStep(nodeFrom,
168+
nodeTo.(FlowSummaryNode).getSummaryNode(), model)
163169
}
164170

165171
private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) {

0 commit comments

Comments
 (0)