-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathExtensions.qll
More file actions
87 lines (76 loc) · 2.99 KB
/
Extensions.qll
File metadata and controls
87 lines (76 loc) · 2.99 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
/**
* This library allows custom extensions to the points-to analysis to incorporate
* custom domain knowledge into the points-to analysis.
*
* This should be considered an advance feature. Modifying the points-to analysis
* can cause queries to give strange and misleading results, if not done with care.
*
* WARNING:
* This module interacts with the internals of points-to analysis and
* the classes here are more likely to change than the rest of the library.
*/
import python
private import semmle.python.pointsto.PointsTo
private import semmle.python.pointsto.PointsToContext
private import semmle.python.objects.TObject
/* Make ObjectInternal visible to save extra imports in user code */
private import semmle.python.objects.ObjectInternal
private import semmle.python.pointsto.Context
abstract class PointsToExtension extends @py_flow_node {
string toString() { result = "PointsToExtension with missing toString" }
abstract predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin);
}
/* Legacy API */
/*
* Custom Facts. This extension mechanism allows you to add custom
* sources of data to the points-to analysis.
*/
/* An example */
/** An extension representing the fact that a variable iterating over range or xrange must be an integer */
class RangeIterationVariableFact extends PointsToExtension {
RangeIterationVariableFact() {
exists(For f, ControlFlowNode iterable |
iterable.getBasicBlock().dominates(this.(ControlFlowNode).getBasicBlock()) and
f.getIter().getAFlowNode() = iterable and
f.getTarget().getAFlowNode() = this and
exists(ObjectInternal range |
PointsTo::pointsTo(iterable, _, range, _) and
range.getClass() = ObjectInternal::builtin("range")
)
)
}
override predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin) {
value = TUnknownInstance(ObjectInternal::builtin("int")) and
origin = this and
context.appliesTo(this)
}
}
/* Python 3.6+ regex module constants */
string short_flag(string flag) {
flag in ["ASCII", "IGNORECASE", "LOCALE", "UNICODE", "MULTILINE", "TEMPLATE"] and
result = flag.prefix(1)
or
flag = "DOTALL" and result = "S"
or
flag = "VERBOSE" and result = "X"
}
class ReModulePointToExtension extends PointsToExtension {
string name;
ReModulePointToExtension() {
exists(ModuleObjectInternal re |
re.getName() = "re" and
PointsTo::pointsTo(this.(AttrNode).getObject(name), _, re, _)
)
}
override predicate pointsTo(Context context, ObjectInternal value, ControlFlowNode origin) {
exists(ModuleObjectInternal sre_constants, CfgOrigin orig, string flag |
(name = flag or name = short_flag(flag)) and
sre_constants.getName() = "sre_constants" and
sre_constants.attribute("SRE_FLAG_" + flag, value, orig) and
origin = orig.asCfgNodeOrHere(this)
) and
this.pointsTo_helper(context)
}
pragma[noinline]
private predicate pointsTo_helper(Context context) { context.appliesTo(this) }
}