Skip to content

Commit 4a3ddfe

Browse files
committed
Use ContentSet a bit
1 parent e877929 commit 4a3ddfe

52 files changed

Lines changed: 199 additions & 318 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1075,9 +1075,9 @@ module Conversions {
10751075
nodeTo = decoding.getOutput()
10761076
) and
10771077
(
1078-
c instanceof TupleElementContent
1078+
c instanceof TupleElementAnyContent
10791079
or
1080-
c instanceof DictionaryElementContent
1080+
c instanceof DictionaryElementAnyContent
10811081
)
10821082
}
10831083

@@ -1087,9 +1087,9 @@ module Conversions {
10871087
nodeTo = encoding.getOutput()
10881088
) and
10891089
(
1090-
c instanceof TupleElementContent
1090+
c instanceof TupleElementAnyContent
10911091
or
1092-
c instanceof DictionaryElementContent
1092+
c instanceof DictionaryElementAnyContent
10931093
)
10941094
}
10951095

@@ -1099,13 +1099,13 @@ module Conversions {
10991099
fmt.getOp() instanceof Mod and
11001100
fmt.getRight() = nodeFrom.asCfgNode()
11011101
) and
1102-
c instanceof TupleElementContent
1102+
c instanceof TupleElementAnyContent
11031103
or
11041104
// format_map
11051105
// see https://docs.python.org/3/library/stdtypes.html#str.format_map
11061106
nodeTo.(MethodCallNode).calls(_, "format_map") and
11071107
nodeTo.(MethodCallNode).getArg(0) = nodeFrom and
1108-
c instanceof DictionaryElementContent
1108+
c instanceof DictionaryElementAnyContent
11091109
}
11101110

11111111
predicate readStep(Node nodeFrom, ContentSet c, Node nodeTo) {

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

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,8 @@ newtype TContent =
758758
// data-flow-private)
759759
index in [0 .. 7]
760760
} or
761+
/** An element of a tuple at any index. */
762+
TTupleElementAnyContent() or
761763
/** An element of a dictionary under a specific key. */
762764
TDictionaryElementContent(string key) {
763765
// {"key": ...}
@@ -870,6 +872,13 @@ class DictionaryElementAnyContent extends TDictionaryElementAnyContent, Content
870872
override string getMaDRepresentation() { result = "DictionaryElementAny" }
871873
}
872874

875+
/** An element of a tuple at any index. */
876+
class TupleElementAnyContent extends TTupleElementAnyContent, Content {
877+
override string toString() { result = "Any tuple element" }
878+
879+
override string getMaDRepresentation() { result = "TupleElementAny" }
880+
}
881+
873882
/** An object attribute. */
874883
class AttributeContent extends TAttributeContent, Content {
875884
private string attr;
@@ -903,13 +912,31 @@ class CapturedVariableContent extends Content, TCapturedVariableContent {
903912
*
904913
* The set may be interpreted differently depending on whether it is
905914
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
915+
*
916+
* Most `ContentSet`s are singletons (i.e. they consist of a single `Content`),
917+
* but `DictionaryElementAnyContent` and `TupleElementAnyContent` act as
918+
* wildcards on the read side: a read at such a `ContentSet` matches *any*
919+
* specific dictionary key / tuple index store. This lets a single `ContentSet`
920+
* stand in for the entire family of per-key/per-index contents, which keeps
921+
* the dataflow `readSetEx` relation small when implicit reads are used (e.g.
922+
* at sinks via `defaultImplicitTaintRead`).
906923
*/
907924
class ContentSet instanceof Content {
908925
/** Gets a content that may be stored into when storing into this set. */
909926
Content getAStoreContent() { result = this }
910927

911928
/** Gets a content that may be read from when reading from this set. */
912-
Content getAReadContent() { result = this }
929+
Content getAReadContent() {
930+
result = this
931+
or
932+
// Wildcard expansion: a read at "any dict element" matches a store at any
933+
// specific dictionary key, and similarly for tuples.
934+
this instanceof DictionaryElementAnyContent and
935+
result instanceof DictionaryElementContent
936+
or
937+
this instanceof TupleElementAnyContent and
938+
result instanceof TupleElementContent
939+
}
913940

914941
/** Gets a textual representation of this content set. */
915942
string toString() { result = super.toString() }

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
7474
cs = TTupleElementContent(index) and result = "TupleElement" and arg = index.toString()
7575
)
7676
or
77+
cs = TTupleElementAnyContent() and result = "TupleElementAny" and arg = ""
78+
or
7779
exists(string key |
7880
cs = TDictionaryElementContent(key) and result = "DictionaryElement" and arg = key
7981
)
@@ -149,6 +151,9 @@ module Private {
149151
exists(TupleElementContent c | c.getIndex() = index and result = content(c))
150152
}
151153

154+
/** Gets a summary component that represents a tuple element at any index. */
155+
SummaryComponent tupleElementAny() { result = content(any(TupleElementAnyContent c)) }
156+
152157
/** Gets a summary component that represents a dictionary element. */
153158
SummaryComponent dictionaryElement(string key) {
154159
exists(DictionaryElementContent c | c.getKey() = key and result = content(c))

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@ predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
1717
*/
1818
bindingset[node]
1919
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) {
20-
// We allow implicit reads of precise content
21-
// imprecise content has already bubled up.
20+
// We allow implicit reads of precise content; imprecise content has already
21+
// bubbled up. We use the wildcard `*Any` content sets here rather than the
22+
// per-key/per-index ones to avoid blowing up the size of `Stage1::readSetEx`
23+
// (otherwise this predicate would expand to one row per (node, distinct key
24+
// or index) and the framework's read-set relation grows quadratically).
25+
// `ContentSet.getAReadContent` expands these wildcards back to the specific
26+
// contents when matching against stores.
2227
exists(node) and
2328
(
24-
c instanceof DataFlow::TupleElementContent
29+
c instanceof DataFlow::TupleElementAnyContent
2530
or
26-
c instanceof DataFlow::DictionaryElementContent
31+
c instanceof DataFlow::DictionaryElementAnyContent
2732
)
2833
}
2934

python/ql/test/2/extractor-tests/hidden/test.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
| .hidden/inner |
12
| .hidden/inner/test.py |
23
| .hidden/module.py |
4+
| folder |
35
| folder/module.py |
46
| package |
57
| package/__init__.py |
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
| Module package |
22
| Module package.__init__ |
33
| Module sys |
4+
| Module sys._jit |
5+
| Module sys.monitoring |
46
| Module test |
Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1 @@
1-
| 8 | ControlFlowNode for ExceptStmt | builtin-class AttributeError |
2-
| 10 | ControlFlowNode for ExceptStmt | builtin-class IndexError |
3-
| 12 | ControlFlowNode for ExceptStmt | builtin-class KeyError |
41
| 14 | ControlFlowNode for ExceptStmt | builtin-class BaseException |
5-
| 23 | ControlFlowNode for ExceptStmt | builtin-class AttributeError |
6-
| 25 | ControlFlowNode for ExceptStmt | builtin-class IndexError |
7-
| 27 | ControlFlowNode for ExceptStmt | builtin-class KeyError |
8-
| 38 | ControlFlowNode for ExceptStmt | builtin-class AttributeError |
9-
| 40 | ControlFlowNode for ExceptStmt | builtin-class IndexError |
10-
| 42 | ControlFlowNode for ExceptStmt | builtin-class KeyError |
11-
| 57 | ControlFlowNode for ExceptStmt | builtin-class IOError |
Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +0,0 @@
1-
| 4 | ControlFlowNode for Subscript | builtin-class IndexError |
2-
| 4 | ControlFlowNode for Subscript | builtin-class KeyError |
3-
| 5 | ControlFlowNode for Attribute | builtin-class AttributeError |
4-
| 7 | ControlFlowNode for Raise | builtin-class Exception |
5-
| 19 | ControlFlowNode for Subscript | builtin-class IndexError |
6-
| 19 | ControlFlowNode for Subscript | builtin-class KeyError |
7-
| 20 | ControlFlowNode for Attribute | builtin-class AttributeError |
8-
| 22 | ControlFlowNode for Raise | builtin-class Exception |
9-
| 30 | ControlFlowNode for Pass | builtin-class Exception |
10-
| 34 | ControlFlowNode for Subscript | builtin-class IndexError |
11-
| 34 | ControlFlowNode for Subscript | builtin-class KeyError |
12-
| 35 | ControlFlowNode for Attribute | builtin-class AttributeError |
13-
| 37 | ControlFlowNode for Raise | builtin-class Exception |
14-
| 53 | ControlFlowNode for Attribute() | builtin-class IOError |
15-
| 54 | ControlFlowNode for Attribute() | builtin-class IOError |
Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
1-
| 4 | ControlFlowNode for Subscript | 10 | ControlFlowNode for ExceptStmt |
2-
| 4 | ControlFlowNode for Subscript | 12 | ControlFlowNode for ExceptStmt |
3-
| 5 | ControlFlowNode for Attribute | 8 | ControlFlowNode for ExceptStmt |
41
| 6 | ControlFlowNode for a() | 8 | ControlFlowNode for ExceptStmt |
52
| 6 | ControlFlowNode for a() | 10 | ControlFlowNode for ExceptStmt |
63
| 6 | ControlFlowNode for a() | 12 | ControlFlowNode for ExceptStmt |
74
| 6 | ControlFlowNode for a() | 14 | ControlFlowNode for ExceptStmt |
8-
| 7 | ControlFlowNode for Raise | 14 | ControlFlowNode for ExceptStmt |
9-
| 19 | ControlFlowNode for Subscript | 25 | ControlFlowNode for ExceptStmt |
10-
| 19 | ControlFlowNode for Subscript | 27 | ControlFlowNode for ExceptStmt |
11-
| 20 | ControlFlowNode for Attribute | 23 | ControlFlowNode for ExceptStmt |
5+
| 7 | ControlFlowNode for Exception() | 8 | ControlFlowNode for ExceptStmt |
6+
| 7 | ControlFlowNode for Exception() | 10 | ControlFlowNode for ExceptStmt |
7+
| 7 | ControlFlowNode for Exception() | 12 | ControlFlowNode for ExceptStmt |
8+
| 7 | ControlFlowNode for Exception() | 14 | ControlFlowNode for ExceptStmt |
129
| 21 | ControlFlowNode for a() | 23 | ControlFlowNode for ExceptStmt |
1310
| 21 | ControlFlowNode for a() | 25 | ControlFlowNode for ExceptStmt |
1411
| 21 | ControlFlowNode for a() | 27 | ControlFlowNode for ExceptStmt |
1512
| 21 | ControlFlowNode for a() | 30 | ControlFlowNode for Pass |
16-
| 22 | ControlFlowNode for Raise | 30 | ControlFlowNode for Pass |
17-
| 34 | ControlFlowNode for Subscript | 40 | ControlFlowNode for ExceptStmt |
18-
| 34 | ControlFlowNode for Subscript | 42 | ControlFlowNode for ExceptStmt |
19-
| 35 | ControlFlowNode for Attribute | 38 | ControlFlowNode for ExceptStmt |
13+
| 22 | ControlFlowNode for Exception() | 23 | ControlFlowNode for ExceptStmt |
14+
| 22 | ControlFlowNode for Exception() | 25 | ControlFlowNode for ExceptStmt |
15+
| 22 | ControlFlowNode for Exception() | 27 | ControlFlowNode for ExceptStmt |
16+
| 22 | ControlFlowNode for Exception() | 30 | ControlFlowNode for Pass |
2017
| 36 | ControlFlowNode for a() | 38 | ControlFlowNode for ExceptStmt |
2118
| 36 | ControlFlowNode for a() | 40 | ControlFlowNode for ExceptStmt |
2219
| 36 | ControlFlowNode for a() | 42 | ControlFlowNode for ExceptStmt |
23-
| 53 | ControlFlowNode for Attribute() | 57 | ControlFlowNode for ExceptStmt |
24-
| 54 | ControlFlowNode for Attribute() | 57 | ControlFlowNode for ExceptStmt |
20+
| 37 | ControlFlowNode for Exception() | 38 | ControlFlowNode for ExceptStmt |
21+
| 37 | ControlFlowNode for Exception() | 40 | ControlFlowNode for ExceptStmt |
22+
| 37 | ControlFlowNode for Exception() | 42 | ControlFlowNode for ExceptStmt |
2523
| 56 | ControlFlowNode for Attribute() | 57 | ControlFlowNode for ExceptStmt |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
| 6 | ControlFlowNode for a() |
2+
| 7 | ControlFlowNode for Exception() |
23
| 21 | ControlFlowNode for a() |
4+
| 22 | ControlFlowNode for Exception() |
35
| 36 | ControlFlowNode for a() |
6+
| 37 | ControlFlowNode for Exception() |
47
| 51 | ControlFlowNode for open() |
58
| 56 | ControlFlowNode for Attribute() |
69
| 58 | ControlFlowNode for Attribute() |

0 commit comments

Comments
 (0)