Skip to content

Commit adbcbef

Browse files
authored
Merge pull request #15551 from yoff/python/avoid-duplicate-model-inclusions
python: Remove `TaintStepFromSummary`
2 parents 4ac8dd7 + 3601773 commit adbcbef

File tree

4 files changed

+53
-45
lines changed

4 files changed

+53
-45
lines changed

python/ql/lib/semmle/python/dataflow/new/FlowSummary.qll

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
private import python
44
private import semmle.python.dataflow.new.DataFlow
5-
private import semmle.python.frameworks.data.ModelsAsData
65
private import semmle.python.ApiGraphs
76
private import internal.FlowSummaryImpl as Impl
87
private import internal.DataFlowUtil
@@ -11,6 +10,7 @@ private import internal.DataFlowPrivate
1110
// import all instances below
1211
private module Summaries {
1312
private import semmle.python.Frameworks
13+
private import semmle.python.frameworks.data.ModelsAsData
1414
}
1515

1616
deprecated class SummaryComponent = Impl::Private::SummaryComponent;
@@ -36,32 +36,3 @@ abstract class SummarizedCallable extends LibraryCallable, Impl::Public::Summari
3636
}
3737

3838
deprecated class RequiredSummaryComponentStack = Impl::Private::RequiredSummaryComponentStack;
39-
40-
private class SummarizedCallableFromModel extends SummarizedCallable {
41-
string type;
42-
string path;
43-
44-
SummarizedCallableFromModel() {
45-
ModelOutput::relevantSummaryModel(type, path, _, _, _) and
46-
this = type + ";" + path
47-
}
48-
49-
override CallCfgNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) }
50-
51-
override ArgumentNode getACallback() {
52-
exists(API::Node base |
53-
ModelOutput::resolvedSummaryRefBase(type, path, base) and
54-
result = base.getAValueReachableFromSource()
55-
)
56-
}
57-
58-
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
59-
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind) |
60-
kind = "value" and
61-
preservesValue = true
62-
or
63-
kind = "taint" and
64-
preservesValue = false
65-
)
66-
}
67-
}

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ newtype TParameterPosition =
5757
// parameter positions available.
5858
FlowSummaryImpl::ParsePositions::isParsedPositionalArgumentPosition(_, index)
5959
} or
60+
TPositionalParameterLowerBoundPosition(int pos) {
61+
FlowSummaryImpl::ParsePositions::isParsedArgumentLowerBoundPosition(_, pos)
62+
} or
6063
TKeywordParameterPosition(string name) {
6164
name = any(Parameter p).getName()
6265
or
@@ -91,6 +94,9 @@ class ParameterPosition extends TParameterPosition {
9194
/** Holds if this position represents a positional parameter at (0-based) `index`. */
9295
predicate isPositional(int index) { this = TPositionalParameterPosition(index) }
9396

97+
/** Holds if this position represents any positional parameter starting from position `pos`. */
98+
predicate isPositionalLowerBound(int pos) { this = TPositionalParameterLowerBoundPosition(pos) }
99+
94100
/** Holds if this position represents a keyword parameter named `name`. */
95101
predicate isKeyword(string name) { this = TKeywordParameterPosition(name) }
96102

@@ -123,6 +129,8 @@ class ParameterPosition extends TParameterPosition {
123129
or
124130
exists(int index | this.isPositional(index) and result = "position " + index)
125131
or
132+
exists(int pos | this.isPositionalLowerBound(pos) and result = "position " + pos + "..")
133+
or
126134
exists(string name | this.isKeyword(name) and result = "keyword " + name)
127135
or
128136
exists(int index | this.isStarArgs(index) and result = "*args at " + index)
@@ -211,6 +219,10 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
211219
or
212220
exists(int index | ppos.isPositional(index) and apos.isPositional(index))
213221
or
222+
exists(int index1, int index2 |
223+
ppos.isPositionalLowerBound(index1) and apos.isPositional(index2) and index2 >= index1
224+
)
225+
or
214226
exists(string name | ppos.isKeyword(name) and apos.isKeyword(name))
215227
or
216228
exists(int index | ppos.isStarArgs(index) and apos.isStarArgs(index))
@@ -360,6 +372,10 @@ abstract class DataFlowFunction extends DataFlowCallable, TFunction {
360372
result.getParameter() = func.getArg(index + this.positionalOffset())
361373
)
362374
or
375+
exists(int index1, int index2 | ppos.isPositionalLowerBound(index1) and index2 >= index1 |
376+
result.getParameter() = func.getArg(index2 + this.positionalOffset())
377+
)
378+
or
363379
exists(string name | ppos.isKeyword(name) | result.getParameter() = func.getArgByName(name))
364380
or
365381
// `*args`

python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ module Input implements InputSig<DataFlowImplSpecific::PythonDataFlow> {
2727
result = i.toString()
2828
)
2929
or
30+
exists(int i |
31+
pos.isPositionalLowerBound(i) and
32+
result = i + ".."
33+
)
34+
or
3035
exists(string name |
3136
pos.isKeyword(name) and
3237
result = name + ":"
@@ -195,6 +200,11 @@ module ParsePositions {
195200
i = AccessPath::parseInt(c)
196201
}
197202

203+
predicate isParsedArgumentLowerBoundPosition(string c, int i) {
204+
isArgBody(c) and
205+
i = AccessPath::parseLowerBound(c)
206+
}
207+
198208
predicate isParsedKeywordArgumentPosition(string c, string argName) {
199209
isArgBody(c) and
200210
c = argName + ":"

python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Shared::ModelOutput as ModelOutput
1717
private import semmle.python.dataflow.new.RemoteFlowSources
1818
private import semmle.python.dataflow.new.DataFlow
1919
private import semmle.python.ApiGraphs
20-
private import semmle.python.dataflow.new.TaintTracking
20+
private import semmle.python.dataflow.new.FlowSummary
2121

2222
/**
2323
* A remote flow source originating from a CSV source row.
@@ -28,20 +28,31 @@ private class RemoteFlowSourceFromCsv extends RemoteFlowSource {
2828
override string getSourceType() { result = "Remote flow (from model)" }
2929
}
3030

31-
/**
32-
* Like `ModelOutput::summaryStep` but with API nodes mapped to data-flow nodes.
33-
*/
34-
private predicate summaryStepNodes(DataFlow::Node pred, DataFlow::Node succ, string kind) {
35-
exists(API::Node predNode, API::Node succNode |
36-
Specific::summaryStep(predNode, succNode, kind) and
37-
pred = predNode.asSink() and
38-
succ = succNode.asSource()
39-
)
40-
}
31+
private class SummarizedCallableFromModel extends SummarizedCallable {
32+
string type;
33+
string path;
34+
35+
SummarizedCallableFromModel() {
36+
ModelOutput::relevantSummaryModel(type, path, _, _, _) and
37+
this = type + ";" + path
38+
}
39+
40+
override DataFlow::CallCfgNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) }
41+
42+
override DataFlow::ArgumentNode getACallback() {
43+
exists(API::Node base |
44+
ModelOutput::resolvedSummaryRefBase(type, path, base) and
45+
result = base.getAValueReachableFromSource()
46+
)
47+
}
4148

42-
/** Taint steps induced by summary models of kind `taint`. */
43-
private class TaintStepFromSummary extends TaintTracking::AdditionalTaintStep {
44-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
45-
summaryStepNodes(pred, succ, "taint")
49+
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
50+
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind) |
51+
kind = "value" and
52+
preservesValue = true
53+
or
54+
kind = "taint" and
55+
preservesValue = false
56+
)
4657
}
4758
}

0 commit comments

Comments
 (0)