Skip to content

Commit 157e38e

Browse files
committed
Python: Remove imprecise container steps
- remove `tupleStoreStep` and `dictStoreStep` from `containerStep` These are imprecise compared to the content being precise. - add implicit reads to recover taint at sinks - add implicit read steps for decoders to supplement the `AdditionalTaintStep` that now only covers when the full container is tainted.
1 parent 6618906 commit 157e38e

File tree

2 files changed

+24
-5
lines changed

2 files changed

+24
-5
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,8 @@ predicate readStep(Node nodeFrom, ContentSet c, Node nodeTo) {
928928
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
929929
or
930930
VariableCapture::readStep(nodeFrom, c, nodeTo)
931+
or
932+
Decodings::decoderReadStep(nodeFrom, c, nodeTo)
931933
}
932934

933935
/** Data flows from a sequence to a subscript of the sequence. */
@@ -983,6 +985,18 @@ predicate attributeReadStep(Node nodeFrom, AttributeContent c, AttrRead nodeTo)
983985
nodeTo.accesses(nodeFrom, c.getAttribute())
984986
}
985987

988+
module Decodings {
989+
private import semmle.python.Concepts
990+
991+
predicate decoderReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
992+
exists(Decoding decoding |
993+
nodeFrom = decoding.getAnInput() and
994+
nodeTo = decoding.getOutput() and
995+
c instanceof DictionaryElementContent
996+
)
997+
}
998+
}
999+
9861000
/**
9871001
* Holds if values stored inside content `c` are cleared at node `n`. For example,
9881002
* any value stored inside `f` is cleared at the pre-update node associated with `x`

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,16 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
1616
* of `c` at sinks and inputs to additional taint steps.
1717
*/
1818
bindingset[node]
19-
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) { none() }
19+
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) {
20+
// We allow implicit reads of precise content
21+
// imprecise content has already bubled up.
22+
exists(node) and
23+
(
24+
c instanceof DataFlow::TupleElementContent
25+
or
26+
c instanceof DataFlow::DictionaryElementContent
27+
)
28+
}
2029

2130
private module Cached {
2231
/**
@@ -178,10 +187,6 @@ predicate containerStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
178187
or
179188
DataFlowPrivate::setStoreStep(nodeFrom, _, nodeTo)
180189
or
181-
DataFlowPrivate::tupleStoreStep(nodeFrom, _, nodeTo)
182-
or
183-
DataFlowPrivate::dictStoreStep(nodeFrom, _, nodeTo)
184-
or
185190
// comprehension, so there is taint-flow from `x` in `[x for x in xs]` to the
186191
// resulting list of the list-comprehension.
187192
//

0 commit comments

Comments
 (0)