Skip to content

Commit df61c4d

Browse files
committed
reintroduce the experiemental queries that use deprecated features
1 parent bfe7e62 commit df61c4d

Some content is hidden

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

54 files changed

+2538
-0
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import semmle.python.dataflow.Implementation
2+
3+
deprecated module TaintTrackingPaths {
4+
predicate edge(TaintTrackingNode src, TaintTrackingNode dest, string label) {
5+
exists(TaintTrackingNode source, TaintTrackingNode sink |
6+
source.getConfiguration().hasFlowPath(source, sink) and
7+
source.getASuccessor*() = src and
8+
src.getASuccessor(label) = dest and
9+
dest.getASuccessor*() = sink
10+
)
11+
}
12+
}
13+
14+
deprecated query predicate edges(TaintTrackingNode fromnode, TaintTrackingNode tonode) {
15+
TaintTrackingPaths::edge(fromnode, tonode, _)
16+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import python
2+
private import Common
3+
import semmle.python.dataflow.TaintTracking
4+
5+
/** An extensible kind of taint representing any kind of string. */
6+
abstract deprecated class StringKind extends TaintKind {
7+
bindingset[this]
8+
StringKind() { this = this }
9+
10+
override TaintKind getTaintOfMethodResult(string name) {
11+
name in [
12+
"capitalize", "casefold", "center", "expandtabs", "format", "format_map", "ljust", "lstrip",
13+
"lower", "replace", "rjust", "rstrip", "strip", "swapcase", "title", "upper", "zfill",
14+
/* encode/decode is technically not correct, but close enough */
15+
"encode", "decode"
16+
] and
17+
result = this
18+
or
19+
name in ["partition", "rpartition", "rsplit", "split", "splitlines"] and
20+
result.(SequenceKind).getItem() = this
21+
}
22+
23+
override TaintKind getTaintForFlowStep(ControlFlowNode fromnode, ControlFlowNode tonode) {
24+
result = this and
25+
(
26+
slice(fromnode, tonode) or
27+
tonode.(BinaryExprNode).getAnOperand() = fromnode or
28+
os_path_join(fromnode, tonode) or
29+
str_format(fromnode, tonode) or
30+
encode_decode(fromnode, tonode) or
31+
to_str(fromnode, tonode) or
32+
f_string(fromnode, tonode)
33+
)
34+
or
35+
result = this and copy_call(fromnode, tonode)
36+
}
37+
38+
override ClassValue getType() {
39+
result = Value::named("bytes") or
40+
result = Value::named("str") or
41+
result = Value::named("unicode")
42+
}
43+
}
44+
45+
deprecated private class StringEqualitySanitizer extends Sanitizer {
46+
StringEqualitySanitizer() { this = "string equality sanitizer" }
47+
48+
/* The test `if untrusted == "KNOWN_VALUE":` sanitizes `untrusted` on its `true` edge. */
49+
override predicate sanitizingEdge(TaintKind taint, PyEdgeRefinement test) {
50+
taint instanceof StringKind and
51+
exists(ControlFlowNode const, Cmpop op | const.getNode() instanceof StrConst |
52+
(
53+
test.getTest().(CompareNode).operands(const, op, _)
54+
or
55+
test.getTest().(CompareNode).operands(_, op, const)
56+
) and
57+
(
58+
op instanceof Eq and test.getSense() = true
59+
or
60+
op instanceof NotEq and test.getSense() = false
61+
)
62+
)
63+
}
64+
}
65+
66+
/** tonode = ....format(fromnode) */
67+
deprecated private predicate str_format(ControlFlowNode fromnode, CallNode tonode) {
68+
tonode.getFunction().(AttrNode).getName() = "format" and
69+
tonode.getAnArg() = fromnode
70+
}
71+
72+
/** tonode = codec.[en|de]code(fromnode) */
73+
deprecated private predicate encode_decode(ControlFlowNode fromnode, CallNode tonode) {
74+
exists(FunctionObject func, string name |
75+
not func.getFunction().isMethod() and
76+
func.getACall() = tonode and
77+
tonode.getAnArg() = fromnode and
78+
func.getName() = name
79+
|
80+
name = "encode" or
81+
name = "decode" or
82+
name = "decodestring"
83+
)
84+
}
85+
86+
/** tonode = str(fromnode) */
87+
deprecated private predicate to_str(ControlFlowNode fromnode, CallNode tonode) {
88+
tonode.getAnArg() = fromnode and
89+
(
90+
tonode = ClassValue::bytes().getACall()
91+
or
92+
tonode = ClassValue::unicode().getACall()
93+
)
94+
}
95+
96+
/** tonode = fromnode[:] */
97+
deprecated private predicate slice(ControlFlowNode fromnode, SubscriptNode tonode) {
98+
exists(Slice all |
99+
all = tonode.getIndex().getNode() and
100+
not exists(all.getStart()) and
101+
not exists(all.getStop()) and
102+
tonode.getObject() = fromnode
103+
)
104+
}
105+
106+
/** tonode = os.path.join(..., fromnode, ...) */
107+
deprecated private predicate os_path_join(ControlFlowNode fromnode, CallNode tonode) {
108+
tonode = Value::named("os.path.join").getACall() and
109+
tonode.getAnArg() = fromnode
110+
}
111+
112+
/** tonode = f"... {fromnode} ..." */
113+
deprecated private predicate f_string(ControlFlowNode fromnode, ControlFlowNode tonode) {
114+
tonode.getNode().(Fstring).getAValue() = fromnode.getNode()
115+
}
116+
117+
/**
118+
* A kind of "taint", representing a dictionary mapping str->"taint"
119+
*
120+
* DEPRECATED: Use `ExternalStringDictKind` instead.
121+
*/
122+
deprecated class StringDictKind extends DictKind {
123+
StringDictKind() { this.getValue() instanceof StringKind }
124+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import python
2+
3+
/** A call that returns a copy (or similar) of the argument */
4+
deprecated predicate copy_call(ControlFlowNode fromnode, CallNode tonode) {
5+
tonode.getFunction().(AttrNode).getObject("copy") = fromnode
6+
or
7+
exists(ModuleValue copy, string name | name = "copy" or name = "deepcopy" |
8+
copy.attr(name).(FunctionValue).getACall() = tonode and
9+
tonode.getArg(0) = fromnode
10+
)
11+
or
12+
tonode.getFunction().pointsTo(Value::named("reversed")) and
13+
tonode.getArg(0) = fromnode
14+
}

0 commit comments

Comments
 (0)