@@ -11,24 +11,23 @@ private import javascript
1111private import semmle.javascript.DynamicPropertyAccess
1212private import semmle.javascript.dataflow.InferredTypes
1313import PrototypePollutingAssignmentCustomizations:: PrototypePollutingAssignment
14+ private import PrototypePollutingAssignmentCustomizations:: PrototypePollutingAssignment as PrototypePollutingAssignment
1415private import semmle.javascript.filters.ClassifyFiles as ClassifyFiles
1516
1617// Materialize flow labels
17- private class ConcreteObjectPrototype extends ObjectPrototype {
18+ deprecated private class ConcreteObjectPrototype extends ObjectPrototype {
1819 ConcreteObjectPrototype ( ) { this = this }
1920}
2021
2122/** A taint-tracking configuration for reasoning about prototype-polluting assignments. */
2223module PrototypePollutingAssignmentConfig implements DataFlow:: StateConfigSig {
23- class FlowState = DataFlow :: FlowLabel ;
24+ class FlowState = PrototypePollutingAssignment :: FlowState ;
2425
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 ( )
2728 }
2829
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 }
3231
3332 predicate isBarrier ( DataFlow:: Node node ) {
3433 node instanceof Sanitizer
@@ -59,28 +58,28 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
5958 node = DataFlow:: MakeBarrierGuard< BarrierGuard > :: getABarrierNode ( )
6059 }
6160
62- predicate isBarrierOut ( DataFlow:: Node node , DataFlow :: FlowLabel lbl ) {
61+ predicate isBarrierOut ( DataFlow:: Node node , FlowState lbl ) {
6362 // Suppress the value-preserving step src -> dst in `extend(dst, src)`. This is modeled as a value-preserving
6463 // step because it preserves all properties, but the destination is not actually Object.prototype.
6564 node = any ( ExtendCall call ) .getASourceOperand ( ) and
66- lbl instanceof ObjectPrototype
65+ lbl = FlowState :: objectPrototype ( )
6766 }
6867
69- predicate isBarrierIn ( DataFlow:: Node node , DataFlow :: FlowLabel lbl ) {
68+ predicate isBarrierIn ( DataFlow:: Node node , FlowState lbl ) {
7069 // FIXME: This should only be an in-barrier for the corresponding flow state, but flow-state specific in-barriers are not supported right now.
7170 isSource ( node , lbl )
7271 }
7372
7473 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
7675 ) {
7776 // Step from x -> obj[x] while switching to the ObjectPrototype label
7877 // (If `x` can have the value `__proto__` then the result can be Object.prototype)
7978 exists ( DynamicPropRead read |
8079 pred = read .getPropertyNameNode ( ) and
8180 succ = read and
82- inlbl . isTaint ( ) and
83- outlbl instanceof ObjectPrototype and
81+ inlbl = FlowState :: taint ( ) and
82+ outlbl = FlowState :: objectPrototype ( ) and
8483 // Exclude cases where the property name came from a property enumeration.
8584 // If the property name is an own property of the base object, the read won't
8685 // return Object.prototype.
@@ -96,31 +95,31 @@ module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig {
9695 proj .isSingletonProjection ( ) and
9796 pred = proj .getASelector ( ) and
9897 succ = proj and
99- inlbl . isTaint ( ) and
100- outlbl instanceof ObjectPrototype
98+ inlbl = FlowState :: taint ( ) and
99+ outlbl = FlowState :: objectPrototype ( )
101100 )
102101 or
103102 // TODO: local field step becomes a jump step, resulting in FPs (closure-lib)
104103 // TODO: localFieldStep is too expensive with dataflow2
105104 // DataFlow::localFieldStep(pred, succ)
106105 none ( )
107106 or
108- inlbl . isTaint ( ) and
107+ inlbl = FlowState :: taint ( ) and
109108 TaintTracking:: defaultTaintStep ( pred , succ ) and
110109 inlbl = outlbl
111110 }
112111
113112 DataFlow:: FlowFeature getAFeature ( ) { result instanceof DataFlow:: FeatureHasSourceCallContext }
114113
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
117116 TaintTracking:: defaultSanitizer ( node )
118117 or
119118 // Don't propagate into the receiver, as the method lookups will generally fail on Object.prototype.
120119 node instanceof DataFlow:: ThisNode and
121- lbl instanceof ObjectPrototype
120+ lbl = FlowState :: objectPrototype ( )
122121 or
123- node = DataFlow:: MakeLabeledBarrierGuard < BarrierGuard > :: getABarrierNode ( lbl )
122+ node = DataFlow:: MakeStateBarrierGuard < FlowState , BarrierGuard > :: getABarrierNode ( lbl )
124123 }
125124}
126125
@@ -173,7 +172,8 @@ deprecated class Configuration extends TaintTracking::Configuration {
173172 override predicate isAdditionalFlowStep (
174173 DataFlow:: Node pred , DataFlow:: Node succ , DataFlow:: FlowLabel inlbl , DataFlow:: FlowLabel outlbl
175174 ) {
176- PrototypePollutingAssignmentConfig:: isAdditionalFlowStep ( pred , inlbl , succ , outlbl )
175+ PrototypePollutingAssignmentConfig:: isAdditionalFlowStep ( pred , FlowState:: fromFlowLabel ( inlbl ) ,
176+ succ , FlowState:: fromFlowLabel ( outlbl ) )
177177 }
178178
179179 override predicate hasFlowPath ( DataFlow:: SourcePathNode source , DataFlow:: SinkPathNode sink ) {
@@ -264,10 +264,10 @@ private class PropertyPresenceCheck extends BarrierGuard, DataFlow::ValueNode {
264264 not isPropertyPresentOnObjectPrototype ( astNode .getPropertyName ( ) )
265265 }
266266
267- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
267+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
268268 e = astNode .getBase ( ) and
269269 outcome = true and
270- label instanceof ObjectPrototype
270+ label = FlowState :: objectPrototype ( )
271271 }
272272}
273273
@@ -279,21 +279,21 @@ private class InExprCheck extends BarrierGuard, DataFlow::ValueNode {
279279 not isPropertyPresentOnObjectPrototype ( astNode .getLeftOperand ( ) .getStringValue ( ) )
280280 }
281281
282- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
282+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
283283 e = astNode .getRightOperand ( ) and
284284 outcome = true and
285- label instanceof ObjectPrototype
285+ label = FlowState :: objectPrototype ( )
286286 }
287287}
288288
289289/** A check of form `e instanceof X`, which is always false for `Object.prototype`. */
290290private class InstanceofCheck extends BarrierGuard , DataFlow:: ValueNode {
291291 override InstanceofExpr astNode ;
292292
293- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
293+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
294294 e = astNode .getLeftOperand ( ) and
295295 outcome = true and
296- label instanceof ObjectPrototype
296+ label = FlowState :: objectPrototype ( )
297297 }
298298}
299299
@@ -311,10 +311,10 @@ private class TypeofCheck extends BarrierGuard, DataFlow::ValueNode {
311311 )
312312 }
313313
314- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
314+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
315315 polarity = outcome and
316316 e = operand and
317- label instanceof ObjectPrototype
317+ label = FlowState :: objectPrototype ( )
318318 }
319319}
320320
@@ -332,10 +332,10 @@ class NumberGuard extends BarrierGuard instanceof DataFlow::CallNode {
332332private class IsArrayCheck extends BarrierGuard , DataFlow:: CallNode {
333333 IsArrayCheck ( ) { this = DataFlow:: globalVarRef ( "Array" ) .getAMemberCall ( "isArray" ) }
334334
335- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
335+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState label ) {
336336 e = this .getArgument ( 0 ) .asExpr ( ) and
337337 outcome = true and
338- label instanceof ObjectPrototype
338+ label = FlowState :: objectPrototype ( )
339339 }
340340}
341341
0 commit comments