Repository navigation
Expand file tree
/
Copy pathPropertyProjection.qll
More file actions
155 lines (131 loc) · 4.24 KB
/
Copy pathPropertyProjection.qll
File metadata and controls
155 lines (131 loc) · 4.24 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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/**
* Provides classes for modelling property projection functions.
*
* Subclass `PropertyProjection` to refine the behavior of the analysis on existing property projections.
* Subclass `CustomPropertyProjection` to introduce new kinds of property projections.
*/
import javascript
/**
* A property projection call such as `_.get(o, 'a.b')`, which is equivalent to `o.a.b`.
*/
abstract class CustomPropertyProjection extends DataFlow::CallNode {
/**
* Gets the argument for the object to project properties from, such as `o` in `_.get(o, 'a.b')`.
*/
abstract DataFlow::Node getObject();
/**
* Gets an argument that selects the properties to project, such as `'a.b'` in `_.get(o, 'a.b')`.
*/
abstract DataFlow::Node getASelector();
/**
* Holds if this call returns the value of a single projected property, as opposed to an object that can contain multiple projected properties.
*/
abstract predicate isSingletonProjection();
}
/**
* A property projection call such as `_.get(o, 'a.b')`, which is equivalent to `o.a.b`.
*/
class PropertyProjection extends DataFlow::CallNode {
CustomPropertyProjection custom;
PropertyProjection() { this = custom }
/**
* Gets the argument for the object to project properties from, such as `o` in `_.get(o, 'a.b')`.
*/
DataFlow::Node getObject() { result = custom.getObject() }
/**
* Gets an argument that selects the properties to project, such as `'a.b'` in `_.get(o, 'a.b')`.
*/
DataFlow::Node getASelector() { result = custom.getASelector() }
/**
* Holds if this call returns the value of a single projected property, as opposed to an object that can contain multiple projected properties.
*
* Examples:
* - This predicate holds for `_.get({a: 'b'}, 'a')`, which returns `'b'`,
* - This predicate does not hold for `_.pick({a: 'b', c: 'd'}}, 'a')`, which returns `{a: 'b'}`,
*/
predicate isSingletonProjection() { custom.isSingletonProjection() }
}
/**
* A simple model of common property projection functions.
*/
private class SimplePropertyProjection extends CustomPropertyProjection {
int objectIndex;
int selectorIndex;
boolean singleton;
SimplePropertyProjection() {
exists (DataFlow::SourceNode callee |
this = callee.getACall() |
singleton = false and (
(
callee = LodashUnderscore::member("pick") and
objectIndex = 0 and
selectorIndex = [1..getNumArgument()]
)
or
(
callee = LodashUnderscore::member("pickBy") and
objectIndex = 0 and
selectorIndex = 1
)
or
exists (string name |
name = "pick" or
name = "pickAll" or
name = "pickBy" |
callee = DataFlow::moduleMember("ramda", name) and
objectIndex = 1 and
selectorIndex = 0
)
or
(
callee = DataFlow::moduleMember("dotty", "search") and
objectIndex = 0 and
selectorIndex = 1
)
)
or
singleton = true and (
(
callee = LodashUnderscore::member("get") and
objectIndex = 0 and
selectorIndex = 1
)
or
(
callee = DataFlow::moduleMember("ramda", "path") and
objectIndex = 1 and
selectorIndex = 0
)
or
(
callee = DataFlow::moduleMember("dottie", "get") and
objectIndex = 0 and
selectorIndex = 1
)
or
(
callee = DataFlow::moduleMember("dotty", "get") and
objectIndex = 0 and
selectorIndex = 1
)
)
)
}
override DataFlow::Node getObject() { result = getArgument(objectIndex) }
override DataFlow::Node getASelector() { result = getArgument(selectorIndex) }
override predicate isSingletonProjection() { singleton = true }
}
/**
* A taint step for a property projection.
*/
private class PropertyProjectionTaintStep extends TaintTracking::AdditionalTaintStep {
PropertyProjection projection;
PropertyProjectionTaintStep() {
projection = this
}
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
// reading from a tainted object yields a tainted result
this = succ and
pred = projection.getObject()
}
}