@@ -192,14 +192,6 @@ string unsafePropName() {
192192 result = "constructor"
193193}
194194
195- /**
196- * A flow label representing an unsafe property name, or an object obtained
197- * by using such a property in a dynamic read.
198- */
199- class UnsafePropLabel extends DataFlow:: FlowLabel {
200- UnsafePropLabel ( ) { this = unsafePropName ( ) }
201- }
202-
203195/**
204196 * Tracks data from property enumerations to dynamic property writes.
205197 *
@@ -233,49 +225,50 @@ class UnsafePropLabel extends DataFlow::FlowLabel {
233225 * a standalone configuration like in most path queries.
234226 */
235227module PropNameTrackingConfig implements DataFlow:: StateConfigSig {
236- class FlowState = DataFlow:: FlowLabel ;
228+ class FlowState extends string {
229+ FlowState ( ) { this = unsafePropName ( ) }
230+ }
237231
238- predicate isSource ( DataFlow:: Node node , DataFlow :: FlowLabel label ) {
239- label instanceof UnsafePropLabel and
232+ predicate isSource ( DataFlow:: Node node , FlowState state ) {
233+ exists ( state ) and
240234 (
241235 isPollutedPropNameSource ( node )
242236 or
243237 node = any ( EnumeratedPropName prop ) .getASourceProp ( )
244238 )
245239 }
246240
247- predicate isSink ( DataFlow:: Node node , DataFlow :: FlowLabel label ) {
248- label instanceof UnsafePropLabel and
241+ predicate isSink ( DataFlow:: Node node , FlowState state ) {
242+ exists ( state ) and
249243 (
250244 dynamicPropWrite ( node , _, _) or
251245 dynamicPropWrite ( _, node , _) or
252246 dynamicPropWrite ( _, _, node )
253247 )
254248 }
255249
256- predicate isBarrier ( DataFlow:: Node node , DataFlow :: FlowLabel label ) {
257- node = DataFlow:: MakeLabeledBarrierGuard < BarrierGuard > :: getABarrierNode ( label )
250+ predicate isBarrier ( DataFlow:: Node node , FlowState state ) {
251+ node = DataFlow:: MakeStateBarrierGuard < FlowState , BarrierGuard > :: getABarrierNode ( state )
258252 }
259253
260254 predicate isAdditionalFlowStep (
261- DataFlow:: Node pred , DataFlow:: FlowLabel predlbl , DataFlow:: Node succ ,
262- DataFlow:: FlowLabel succlbl
255+ DataFlow:: Node node1 , FlowState state1 , DataFlow:: Node node2 , FlowState state2
263256 ) {
264- predlbl instanceof UnsafePropLabel and
265- succlbl = predlbl and
257+ exists ( state1 ) and
258+ state2 = state1 and
266259 (
267260 // Step through `p -> x[p]`
268261 exists ( DataFlow:: PropRead read |
269- pred = read .getPropertyNameExpr ( ) .flow ( ) and
262+ node1 = read .getPropertyNameExpr ( ) .flow ( ) and
270263 not read .( DynamicPropRead ) .hasDominatingAssignment ( ) and
271- succ = read
264+ node2 = read
272265 )
273266 or
274267 // Step through `x -> x[p]`
275268 exists ( DynamicPropRead read |
276269 not read .hasDominatingAssignment ( ) and
277- pred = read .getBase ( ) and
278- succ = read
270+ node1 = read .getBase ( ) and
271+ node2 = read
279272 )
280273 )
281274 }
@@ -286,6 +279,8 @@ module PropNameTrackingConfig implements DataFlow::StateConfigSig {
286279 }
287280}
288281
282+ class FlowState = PropNameTrackingConfig:: FlowState ;
283+
289284module PropNameTracking = DataFlow:: GlobalWithState< PropNameTrackingConfig > ;
290285
291286/**
@@ -298,9 +293,9 @@ abstract class BarrierGuard extends DataFlow::Node {
298293 predicate blocksExpr ( boolean outcome , Expr e ) { none ( ) }
299294
300295 /**
301- * Holds if this node acts as a barrier for `label `, blocking further flow from `e` if `this` evaluates to `outcome`.
296+ * Holds if this node acts as a barrier for `state `, blocking further flow from `e` if `this` evaluates to `outcome`.
302297 */
303- predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) { none ( ) }
298+ predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) { none ( ) }
304299}
305300
306301/**
@@ -315,10 +310,10 @@ class DenyListEqualityGuard extends BarrierGuard, DataFlow::ValueNode {
315310 propName = unsafePropName ( )
316311 }
317312
318- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
313+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) {
319314 e = astNode .getAnOperand ( ) and
320315 outcome = astNode .getPolarity ( ) .booleanNot ( ) and
321- label = propName
316+ state = propName
322317 }
323318}
324319
@@ -333,10 +328,9 @@ class AllowListEqualityGuard extends BarrierGuard, DataFlow::ValueNode {
333328 astNode .getAnOperand ( ) instanceof Literal
334329 }
335330
336- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
331+ override predicate blocksExpr ( boolean outcome , Expr e ) {
337332 e = astNode .getAnOperand ( ) and
338- outcome = astNode .getPolarity ( ) and
339- label instanceof UnsafePropLabel
333+ outcome = astNode .getPolarity ( )
340334 }
341335}
342336
@@ -382,24 +376,24 @@ class InExprGuard extends BarrierGuard, DataFlow::ValueNode {
382376/**
383377 * A sanitizer guard for `instanceof` expressions.
384378 *
385- * `Object.prototype instanceof X` is never true, so this blocks the `__proto__` label .
379+ * `Object.prototype instanceof X` is never true, so this blocks the `__proto__` state .
386380 *
387381 * It is still possible to get to `Function.prototype` through `constructor.constructor.prototype`
388- * so we do not block the `constructor` label .
382+ * so we do not block the `constructor` state .
389383 */
390384class InstanceOfGuard extends BarrierGuard , DataFlow:: ValueNode {
391385 override InstanceOfExpr astNode ;
392386
393- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
394- e = astNode .getLeftOperand ( ) and outcome = true and label = "__proto__"
387+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) {
388+ e = astNode .getLeftOperand ( ) and outcome = true and state = "__proto__"
395389 }
396390}
397391
398392/**
399393 * Sanitizer guard of form `typeof x === "object"` or `typeof x === "function"`.
400394 *
401- * The former blocks the `constructor` label as that payload must pass through a function,
402- * and the latter blocks the `__proto__` label as that only passes through objects.
395+ * The former blocks the `constructor` state as that payload must pass through a function,
396+ * and the latter blocks the `__proto__` state as that only passes through objects.
403397 */
404398class TypeofGuard extends BarrierGuard , DataFlow:: ValueNode {
405399 override EqualityTest astNode ;
@@ -408,15 +402,15 @@ class TypeofGuard extends BarrierGuard, DataFlow::ValueNode {
408402
409403 TypeofGuard ( ) { TaintTracking:: isTypeofGuard ( astNode , operand , tag ) }
410404
411- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel label ) {
405+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) {
412406 e = operand and
413407 outcome = astNode .getPolarity ( ) and
414408 (
415409 tag = "object" and
416- label = "constructor"
410+ state = "constructor"
417411 or
418412 tag = "function" and
419- label = "__proto__"
413+ state = "__proto__"
420414 )
421415 or
422416 e = operand and
@@ -425,10 +419,10 @@ class TypeofGuard extends BarrierGuard, DataFlow::ValueNode {
425419 // If something is not an object, sanitize object, as both must end
426420 // in non-function prototype object.
427421 tag = "object" and
428- label instanceof UnsafePropLabel
422+ exists ( state )
429423 or
430424 tag = "function" and
431- label = "constructor"
425+ state = "constructor"
432426 )
433427 }
434428}
@@ -437,19 +431,19 @@ class TypeofGuard extends BarrierGuard, DataFlow::ValueNode {
437431 * A check of form `["__proto__"].includes(x)` or similar.
438432 */
439433class DenyListInclusionGuard extends BarrierGuard , InclusionTest {
440- UnsafePropLabel label ;
434+ string blockedProp ;
441435
442436 DenyListInclusionGuard ( ) {
443437 exists ( DataFlow:: ArrayCreationNode array |
444- array .getAnElement ( ) .getStringValue ( ) = label and
438+ array .getAnElement ( ) .getStringValue ( ) = blockedProp and
445439 array .flowsTo ( this .getContainerNode ( ) )
446440 )
447441 }
448442
449- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel lbl ) {
443+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) {
450444 outcome = this .getPolarity ( ) .booleanNot ( ) and
451445 e = this .getContainedNode ( ) .asExpr ( ) and
452- label = lbl
446+ blockedProp = state
453447 }
454448}
455449
@@ -464,9 +458,8 @@ class AllowListInclusionGuard extends BarrierGuard {
464458 not this = any ( MembershipCandidate:: ObjectPropertyNameMembershipCandidate c ) .getTest ( ) // handled with more precision in `HasOwnPropertyGuard`
465459 }
466460
467- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow:: FlowLabel lbl ) {
468- this .( TaintTracking:: AdditionalBarrierGuard ) .blocksExpr ( outcome , e ) and
469- lbl instanceof UnsafePropLabel
461+ override predicate blocksExpr ( boolean outcome , Expr e ) {
462+ this .( TaintTracking:: AdditionalBarrierGuard ) .blocksExpr ( outcome , e )
470463 }
471464}
472465
@@ -482,10 +475,10 @@ class IsPlainObjectGuard extends BarrierGuard, DataFlow::CallNode {
482475 )
483476 }
484477
485- override predicate blocksExpr ( boolean outcome , Expr e , DataFlow :: FlowLabel lbl ) {
478+ override predicate blocksExpr ( boolean outcome , Expr e , FlowState state ) {
486479 e = this .getArgument ( 0 ) .asExpr ( ) and
487480 outcome = true and
488- lbl = "constructor"
481+ state = "constructor"
489482 }
490483}
491484
0 commit comments