@@ -11,24 +11,23 @@ private import javascript
11
11
private import semmle.javascript.DynamicPropertyAccess
12
12
private import semmle.javascript.dataflow.InferredTypes
13
13
import PrototypePollutingAssignmentCustomizations:: PrototypePollutingAssignment
14
+ private import PrototypePollutingAssignmentCustomizations:: PrototypePollutingAssignment as PrototypePollutingAssignment
14
15
private import semmle.javascript.filters.ClassifyFiles as ClassifyFiles
15
16
16
17
// Materialize flow labels
17
- private class ConcreteObjectPrototype extends ObjectPrototype {
18
+ deprecated private class ConcreteObjectPrototype extends ObjectPrototype {
18
19
ConcreteObjectPrototype ( ) { this = this }
19
20
}
20
21
21
22
/** A taint-tracking configuration for reasoning about prototype-polluting assignments. */
22
23
module PrototypePollutingAssignmentConfig implements DataFlow:: StateConfigSig {
23
- class FlowState = DataFlow :: FlowLabel ;
24
+ class FlowState = PrototypePollutingAssignment :: FlowState ;
24
25
25
- predicate isSource ( DataFlow:: Node node , DataFlow :: FlowLabel label ) {
26
- node instanceof Source and label . isTaint ( )
26
+ predicate isSource ( DataFlow:: Node node , FlowState label ) {
27
+ node instanceof Source and label = FlowState :: taint ( )
27
28
}
28
29
29
- predicate isSink ( DataFlow:: Node node , DataFlow:: FlowLabel lbl ) {
30
- node .( Sink ) .getAFlowLabel ( ) = lbl
31
- }
30
+ predicate isSink ( DataFlow:: Node node , FlowState lbl ) { node .( Sink ) .getAFlowState ( ) = lbl }
32
31
33
32
predicate isBarrier ( DataFlow:: Node node ) {
34
33
node instanceof Sanitizer
@@ -59,28 +58,28 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
59
58
node = DataFlow:: MakeBarrierGuard< BarrierGuard > :: getABarrierNode ( )
60
59
}
61
60
62
- predicate isBarrierOut ( DataFlow:: Node node , DataFlow :: FlowLabel lbl ) {
61
+ predicate isBarrierOut ( DataFlow:: Node node , FlowState lbl ) {
63
62
// Suppress the value-preserving step src -> dst in `extend(dst, src)`. This is modeled as a value-preserving
64
63
// step because it preserves all properties, but the destination is not actually Object.prototype.
65
64
node = any ( ExtendCall call ) .getASourceOperand ( ) and
66
- lbl instanceof ObjectPrototype
65
+ lbl = FlowState :: objectPrototype ( )
67
66
}
68
67
69
- predicate isBarrierIn ( DataFlow:: Node node , DataFlow :: FlowLabel lbl ) {
68
+ predicate isBarrierIn ( DataFlow:: Node node , FlowState lbl ) {
70
69
// FIXME: This should only be an in-barrier for the corresponding flow state, but flow-state specific in-barriers are not supported right now.
71
70
isSource ( node , lbl )
72
71
}
73
72
74
73
predicate isAdditionalFlowStep (
75
- DataFlow:: Node pred , DataFlow :: FlowLabel inlbl , DataFlow:: Node succ , DataFlow :: FlowLabel outlbl
74
+ DataFlow:: Node pred , FlowState inlbl , DataFlow:: Node succ , FlowState outlbl
76
75
) {
77
76
// Step from x -> obj[x] while switching to the ObjectPrototype label
78
77
// (If `x` can have the value `__proto__` then the result can be Object.prototype)
79
78
exists ( DynamicPropRead read |
80
79
pred = read .getPropertyNameNode ( ) and
81
80
succ = read and
82
- inlbl . isTaint ( ) and
83
- outlbl instanceof ObjectPrototype and
81
+ inlbl = FlowState :: taint ( ) and
82
+ outlbl = FlowState :: objectPrototype ( ) and
84
83
// Exclude cases where the property name came from a property enumeration.
85
84
// If the property name is an own property of the base object, the read won't
86
85
// return Object.prototype.
@@ -96,31 +95,31 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
96
95
proj .isSingletonProjection ( ) and
97
96
pred = proj .getASelector ( ) and
98
97
succ = proj and
99
- inlbl . isTaint ( ) and
100
- outlbl instanceof ObjectPrototype
98
+ inlbl = FlowState :: taint ( ) and
99
+ outlbl = FlowState :: objectPrototype ( )
101
100
)
102
101
or
103
102
// TODO: local field step becomes a jump step, resulting in FPs (closure-lib)
104
103
// TODO: localFieldStep is too expensive with dataflow2
105
104
// DataFlow::localFieldStep(pred, succ)
106
105
none ( )
107
106
or
108
- inlbl . isTaint ( ) and
107
+ inlbl = FlowState :: taint ( ) and
109
108
TaintTracking:: defaultTaintStep ( pred , succ ) and
110
109
inlbl = outlbl
111
110
}
112
111
113
112
DataFlow:: FlowFeature getAFeature ( ) { result instanceof DataFlow:: FeatureHasSourceCallContext }
114
113
115
- predicate isBarrier ( DataFlow:: Node node , DataFlow :: FlowLabel lbl ) {
116
- lbl . isTaint ( ) and
114
+ predicate isBarrier ( DataFlow:: Node node , FlowState lbl ) {
115
+ lbl = FlowState :: taint ( ) and
117
116
TaintTracking:: defaultSanitizer ( node )
118
117
or
119
118
// Don't propagate into the receiver, as the method lookups will generally fail on Object.prototype.
120
119
node instanceof DataFlow:: ThisNode and
121
- lbl instanceof ObjectPrototype
120
+ lbl = FlowState :: objectPrototype ( )
122
121
or
123
- node = DataFlow:: MakeLabeledBarrierGuard < BarrierGuard > :: getABarrierNode ( lbl )
122
+ node = DataFlow:: MakeStateBarrierGuard < FlowState , BarrierGuard > :: getABarrierNode ( lbl )
124
123
}
125
124
}
126
125
@@ -173,7 +172,8 @@ deprecated class Configuration extends TaintTracking::Configuration {
173
172
override predicate isAdditionalFlowStep (
174
173
DataFlow:: Node pred , DataFlow:: Node succ , DataFlow:: FlowLabel inlbl , DataFlow:: FlowLabel outlbl
175
174
) {
176
- PrototypePollutingAssignmentConfig:: isAdditionalFlowStep ( pred , inlbl , succ , outlbl )
175
+ PrototypePollutingAssignmentConfig:: isAdditionalFlowStep ( pred , FlowState:: fromFlowLabel ( inlbl ) ,
176
+ succ , FlowState:: fromFlowLabel ( outlbl ) )
177
177
}
178
178
179
179
override predicate hasFlowPath ( DataFlow:: SourcePathNode source , DataFlow:: SinkPathNode sink ) {
@@ -264,10 +264,10 @@ private class PropertyPresenceCheck extends BarrierGuard, DataFlow::ValueNode {
264
264
not isPropertyPresentOnObjectPrototype ( astNode .getPropertyName ( ) )
265
265
}
266
266
267
- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
267
+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
268
268
e = astNode .getBase ( ) and
269
269
outcome = true and
270
- label instanceof ObjectPrototype
270
+ label = FlowState :: objectPrototype ( )
271
271
}
272
272
}
273
273
@@ -279,21 +279,21 @@ private class InExprCheck extends BarrierGuard, DataFlow::ValueNode {
279
279
not isPropertyPresentOnObjectPrototype ( astNode .getLeftOperand ( ) .getStringValue ( ) )
280
280
}
281
281
282
- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
282
+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
283
283
e = astNode .getRightOperand ( ) and
284
284
outcome = true and
285
- label instanceof ObjectPrototype
285
+ label = FlowState :: objectPrototype ( )
286
286
}
287
287
}
288
288
289
289
/** A check of form `e instanceof X`, which is always false for `Object.prototype`. */
290
290
private class InstanceofCheck extends BarrierGuard , DataFlow:: ValueNode {
291
291
override InstanceofExpr astNode ;
292
292
293
- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
293
+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
294
294
e = astNode .getLeftOperand ( ) and
295
295
outcome = true and
296
- label instanceof ObjectPrototype
296
+ label = FlowState :: objectPrototype ( )
297
297
}
298
298
}
299
299
@@ -311,10 +311,10 @@ private class TypeofCheck extends BarrierGuard, DataFlow::ValueNode {
311
311
)
312
312
}
313
313
314
- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
314
+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
315
315
polarity = outcome and
316
316
e = operand and
317
- label instanceof ObjectPrototype
317
+ label = FlowState :: objectPrototype ( )
318
318
}
319
319
}
320
320
@@ -332,10 +332,10 @@ class NumberGuard extends BarrierGuard instanceof DataFlow::CallNode {
332
332
private class IsArrayCheck extends BarrierGuard , DataFlow:: CallNode {
333
333
IsArrayCheck ( ) { this = DataFlow:: globalVarRef ( "Array" ) .getAMemberCall ( "isArray" ) }
334
334
335
- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
335
+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
336
336
e = this .getArgument ( 0 ) .asExpr ( ) and
337
337
outcome = true and
338
- label instanceof ObjectPrototype
338
+ label = FlowState :: objectPrototype ( )
339
339
}
340
340
}
341
341
0 commit comments