@@ -339,29 +339,67 @@ class ContentSet instanceof TContentSet {
339339 */
340340signature predicate guardChecksSig ( Node g , Expr e , boolean branch ) ;
341341
342+ bindingset [ this ]
343+ private signature class ParamSig ;
344+
345+ private module WithParam< ParamSig P> {
346+ /**
347+ * Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
348+ *
349+ * The expression `e` is expected to be a syntactic part of the guard `g`.
350+ * For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
351+ * the argument `x`.
352+ */
353+ signature predicate guardChecksSig ( Node g , Expr e , boolean branch , P param ) ;
354+ }
355+
342356/**
343357 * Provides a set of barrier nodes for a guard that validates an expression.
344358 *
345359 * This is expected to be used in `isBarrier`/`isSanitizer` definitions
346360 * in data flow and taint tracking.
347361 */
348362module BarrierGuard< guardChecksSig / 3 guardChecks> {
363+ private predicate guardChecks ( Node g , Expr e , boolean branch , Unit param ) {
364+ guardChecks ( g , e , branch ) and exists ( param )
365+ }
366+
367+ private module B = ParameterizedBarrierGuard< Unit , guardChecks / 4 > ;
368+
369+ /** Gets a node that is safely guarded by the given guard check. */
370+ Node getABarrierNode ( ) { result = B:: getABarrierNode ( _) }
371+
372+ /**
373+ * Gets a node that is safely guarded by the given guard check.
374+ */
375+ Node getABarrierNodeForGuard ( Node guardCheck ) {
376+ result = B:: getABarrierNodeForGuard ( guardCheck , _)
377+ }
378+ }
379+
380+ /**
381+ * Provides a set of barrier nodes for a guard that validates an expression.
382+ *
383+ * This is expected to be used in `isBarrier`/`isSanitizer` definitions
384+ * in data flow and taint tracking.
385+ */
386+ module ParameterizedBarrierGuard< ParamSig P, WithParam< P > :: guardChecksSig / 4 guardChecks> {
349387 /** Gets a node that is safely guarded by the given guard check. */
350- Node getABarrierNode ( ) {
388+ Node getABarrierNode ( P param ) {
351389 exists ( ControlFlow:: ConditionGuardNode guard , SsaWithFields var |
352390 result = pragma [ only_bind_out ] ( var ) .getAUse ( )
353391 |
354- guards ( _, guard , _, var ) and
392+ guards ( _, guard , _, var , param ) and
355393 pragma [ only_bind_out ] ( guard ) .dominates ( result .getBasicBlock ( ) )
356394 )
357395 }
358396
359397 /**
360398 * Gets a node that is safely guarded by the given guard check.
361399 */
362- Node getABarrierNodeForGuard ( Node guardCheck ) {
400+ Node getABarrierNodeForGuard ( Node guardCheck , P param ) {
363401 exists ( ControlFlow:: ConditionGuardNode guard , SsaWithFields var | result = var .getAUse ( ) |
364- guards ( guardCheck , guard , _, var ) and
402+ guards ( guardCheck , guard , _, var , param ) and
365403 guard .dominates ( result .getBasicBlock ( ) )
366404 )
367405 }
@@ -373,22 +411,24 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
373411 * This predicate exists to enforce a good join order in `getAGuardedNode`.
374412 */
375413 pragma [ noinline]
376- private predicate guards ( Node g , ControlFlow:: ConditionGuardNode guard , Node nd , SsaWithFields ap ) {
377- guards ( g , guard , nd ) and nd = ap .getAUse ( )
414+ private predicate guards (
415+ Node g , ControlFlow:: ConditionGuardNode guard , Node nd , SsaWithFields ap , P param
416+ ) {
417+ guards ( g , guard , nd , param ) and nd = ap .getAUse ( )
378418 }
379419
380420 /**
381421 * Holds if `guard` marks a point in the control-flow graph where `g`
382422 * is known to validate `nd`.
383423 */
384- private predicate guards ( Node g , ControlFlow:: ConditionGuardNode guard , Node nd ) {
424+ private predicate guards ( Node g , ControlFlow:: ConditionGuardNode guard , Node nd , P param ) {
385425 exists ( boolean branch |
386- guardChecks ( g , nd .asExpr ( ) , branch ) and
426+ guardChecks ( g , nd .asExpr ( ) , branch , param ) and
387427 guard .ensures ( g , branch )
388428 )
389429 or
390430 exists ( DataFlow:: Property p , Node resNode , Node check , boolean outcome |
391- guardingCall ( g , _, _, _, p , _, nd , resNode ) and
431+ guardingCall ( g , _, _, _, p , _, nd , resNode , param ) and
392432 p .checkOn ( check , outcome , resNode ) and
393433 guard .ensures ( pragma [ only_bind_into ] ( check ) , outcome )
394434 )
@@ -405,9 +445,9 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
405445 pragma [ noinline]
406446 private predicate guardingCall (
407447 Node g , Function f , FunctionInput inp , FunctionOutput outp , DataFlow:: Property p , CallNode c ,
408- Node nd , Node resNode
448+ Node nd , Node resNode , P param
409449 ) {
410- guardingFunction ( g , f , inp , outp , p ) and
450+ guardingFunction ( g , f , inp , outp , p , param ) and
411451 c = f .getACall ( ) and
412452 nd = getInputNode ( inp , c ) and
413453 localFlow ( getOutputNode ( outp , c ) , resNode )
@@ -438,15 +478,15 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
438478 * `false`, `nil` or a non-`nil` value.)
439479 */
440480 private predicate guardingFunction (
441- Node g , Function f , FunctionInput inp , FunctionOutput outp , DataFlow:: Property p
481+ Node g , Function f , FunctionInput inp , FunctionOutput outp , DataFlow:: Property p , P param
442482 ) {
443483 exists ( FuncDecl fd , Node arg , Node ret |
444484 fd .getFunction ( ) = f and
445485 localFlow ( inp .getExitNode ( fd ) , pragma [ only_bind_out ] ( arg ) ) and
446486 (
447487 // Case: a function like "if someBarrierGuard(arg) { return true } else { return false }"
448488 exists ( ControlFlow:: ConditionGuardNode guard |
449- guards ( g , pragma [ only_bind_out ] ( guard ) , arg ) and
489+ guards ( g , pragma [ only_bind_out ] ( guard ) , arg , param ) and
450490 guard .dominates ( pragma [ only_bind_out ] ( ret ) .getBasicBlock ( ) )
451491 |
452492 onlyPossibleReturnSatisfyingProperty ( fd , outp , ret , p )
@@ -456,7 +496,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
456496 // or "return !someBarrierGuard(arg) && otherCond(...)"
457497 exists ( boolean outcome |
458498 ret = getUniqueOutputNode ( fd , outp ) and
459- guardChecks ( g , arg .asExpr ( ) , outcome ) and
499+ guardChecks ( g , arg .asExpr ( ) , outcome , param ) and
460500 // This predicate's contract is (p holds of ret ==> arg is checked),
461501 // (and we have (this has outcome ==> arg is checked))
462502 // but p.checkOn(ret, outcome, this) gives us (ret has outcome ==> p holds of this),
@@ -471,7 +511,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
471511 DataFlow:: Property outpProp
472512 |
473513 ret = getUniqueOutputNode ( fd , outp ) and
474- guardingFunction ( g , f2 , inp2 , outp2 , outpProp ) and
514+ guardingFunction ( g , f2 , inp2 , outp2 , outpProp , param ) and
475515 c = f2 .getACall ( ) and
476516 arg = inp2 .getNode ( c ) and
477517 (
0 commit comments