-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathStringAttributes.qll
More file actions
92 lines (83 loc) · 2.52 KB
/
StringAttributes.qll
File metadata and controls
92 lines (83 loc) · 2.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import python
private import LegacyPointsTo
predicate string_attribute_all(ControlFlowNodeWithPointsTo n, string attr) {
(n.getNode() instanceof Unicode or n.getNode() instanceof Bytes) and
attr = "const"
or
exists(Object s |
n.refersTo(s, theBytesType(), _) and
attr = "bytes" and
// We are only interested in bytes if they may cause an exception if
// implicitly converted to unicode. ASCII is safe.
not s.(StringObject).isAscii()
)
}
predicate tracked_object(ControlFlowNode obj, string attr) {
tracked_object_all(obj, attr)
or
tracked_object_any(obj, attr)
}
predicate open_file(Object obj) {
obj.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(Object::builtin("open"))
}
predicate string_attribute_any(ControlFlowNodeWithPointsTo n, string attr) {
attr = "user-input" and
exists(Object input | n.(CallNode).getFunction().(ControlFlowNodeWithPointsTo).refersTo(input) |
if major_version() = 2
then input = Object::builtin("raw_input")
else input = Object::builtin("input")
)
or
attr = "file-input" and
exists(Object fd |
n.(CallNode)
.getFunction()
.(AttrNode)
.getObject("read")
.(ControlFlowNodeWithPointsTo)
.refersTo(fd)
|
open_file(fd)
)
or
n.refersTo(_, theUnicodeType(), _) and attr = "unicode"
}
predicate tracked_object_any(ControlFlowNode obj, string attr) {
string_attribute_any(obj, attr)
or
exists(ControlFlowNode other | tracking_step(other, obj) | tracked_object_any(other, attr))
}
predicate tracked_object_all(ControlFlowNode obj, string attr) {
string_attribute_all(obj, attr)
or
forex(ControlFlowNode other | tracking_step(other, obj) | tracked_object_all(other, attr))
}
predicate tracked_call_step(ControlFlowNode ret, ControlFlowNode call) {
exists(FunctionObject func, Return r |
func.getACall() = call and
func.getFunction() = r.getScope() and
r.getValue() = ret.getNode()
)
}
ControlFlowNode sequence_for_iterator(ControlFlowNode f) {
exists(For for | f.getNode() = for.getTarget() |
result.getNode() = for.getIter() and
result.getBasicBlock().dominates(f.getBasicBlock())
)
}
pragma[noinline]
private predicate tracking_step(ControlFlowNode src, ControlFlowNodeWithPointsTo dest) {
src = dest.(BinaryExprNode).getAnOperand()
or
src = dest.(UnaryExprNode).getOperand()
or
src = sequence_for_iterator(dest)
or
src = dest.(AttrNode).getObject()
or
src = dest.(SubscriptNode).getObject()
or
tracked_call_step(src, dest)
or
dest.refersTo(src)
}