@@ -1198,6 +1198,21 @@ module Make<LocationSig Location, InputSig<Location> Input> {
11981198 * previous definitions or reads.
11991199 */
12001200 default predicate allowFlowIntoUncertainDef ( UncertainWriteDefinition def ) { none ( ) }
1201+
1202+ /** A (potential) guard. */
1203+ class Guard {
1204+ /** Gets a textual representation of this guard. */
1205+ string toString ( ) ;
1206+
1207+ /** Holds if the `i`th node of basic block `bb` evaluates this guard. */
1208+ predicate hasCfgNode ( BasicBlock bb , int i ) ;
1209+ }
1210+
1211+ /** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
1212+ predicate guardControlsBlock ( Guard guard , BasicBlock bb , boolean branch ) ;
1213+
1214+ /** Gets an immediate conditional successor of basic block `bb`, if any. */
1215+ BasicBlock getAConditionalBasicBlockSuccessor ( BasicBlock bb , boolean branch ) ;
12011216 }
12021217
12031218 /**
@@ -1294,6 +1309,11 @@ module Make<LocationSig Location, InputSig<Location> Input> {
12941309 }
12951310 }
12961311
1312+ cached
1313+ private predicate ssaInputNode ( SsaInputDefinitionExt def , BasicBlock input ) {
1314+ def .hasInputFromBlock ( _, _, _, _, input )
1315+ }
1316+
12971317 private newtype TNode =
12981318 TParamNode ( DfInput:: Parameter p ) or
12991319 TExprNode ( DfInput:: Expr e , Boolean isPost ) {
@@ -1305,9 +1325,7 @@ module Make<LocationSig Location, InputSig<Location> Input> {
13051325 isPost = false
13061326 } or
13071327 TSsaDefinitionNode ( DefinitionExt def ) or
1308- TSsaInputNode ( SsaInputDefinitionExt def , BasicBlock input ) {
1309- def .hasInputFromBlock ( _, _, _, _, input )
1310- }
1328+ TSsaInputNode ( SsaInputDefinitionExt def , BasicBlock input ) { ssaInputNode ( def , input ) }
13111329
13121330 /**
13131331 * A data flow node that we need to reference in the value step relation.
@@ -1577,94 +1595,46 @@ module Make<LocationSig Location, InputSig<Location> Input> {
15771595 nodeTo .( ExprNode ) .getExpr ( ) = getARead ( def )
15781596 }
15791597
1580- /** Provides the input to `BarrierGuards`. */
1581- signature module BarrierGuardsInputSig {
1582- /** A (potential) guard. */
1583- class Guard {
1584- /** Gets a textual representation of this guard. */
1585- string toString ( ) ;
1598+ pragma [ nomagic]
1599+ private predicate guardControlsSsaRead (
1600+ DfInput:: Guard g , boolean branch , Definition def , ExprNode n
1601+ ) {
1602+ exists ( BasicBlock bb , DfInput:: Expr e |
1603+ e = n .getExpr ( ) and
1604+ getARead ( def ) = e and
1605+ DfInput:: guardControlsBlock ( g , bb , branch ) and
1606+ e .hasCfgNode ( bb , _)
1607+ )
1608+ }
15861609
1587- /** Holds if the `i`th node of basic block `bb` evaluates this guard. */
1588- predicate hasCfgNode ( BasicBlock bb , int i ) ;
1589- }
1610+ pragma [ nomagic]
1611+ private predicate guardControlsPhiInput (
1612+ DfInput:: Guard g , boolean branch , Definition def , BasicBlock input , SsaInputDefinitionExt phi
1613+ ) {
1614+ phi .hasInputFromBlock ( def , _, _, _, input ) and
1615+ (
1616+ DfInput:: guardControlsBlock ( g , input , branch )
1617+ or
1618+ exists ( int last |
1619+ last = input .length ( ) - 1 and
1620+ g .hasCfgNode ( input , last ) and
1621+ DfInput:: getAConditionalBasicBlockSuccessor ( input , branch ) = phi .getBasicBlock ( )
1622+ )
1623+ )
1624+ }
15901625
1591- /** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
1592- predicate guardControlsBlock ( Guard guard , BasicBlock bb , boolean branch ) ;
1593-
1594- /** Gets an immediate conditional successor of basic block `bb`, if any. */
1595- BasicBlock getAConditionalBasicBlockSuccessor ( BasicBlock bb , boolean branch ) ;
1596- }
1597-
1598- /** Provides an implementatino of the `BarrierGuard` module. */
1599- module BarrierGuards< BarrierGuardsInputSig BgInput> {
1600- /**
1601- * Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
1602- *
1603- * The expression `e` is expected to be a syntactic part of the guard `g`.
1604- * For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
1605- * the argument `x`.
1606- */
1607- signature predicate guardChecksSig ( BgInput:: Guard g , DfInput:: Expr e , boolean branch ) ;
1608-
1609- /**
1610- * Provides a set of barrier nodes for a guard that validates an expression.
1611- *
1612- * This is expected to be used in `isBarrier`/`isSanitizer` definitions
1613- * in data flow and taint tracking.
1614- */
1615- module BarrierGuard< guardChecksSig / 3 guardChecks> {
1616- pragma [ nomagic]
1617- private predicate guardChecksSsaDef ( BgInput:: Guard g , boolean branch , Definition def ) {
1618- guardChecks ( g , getARead ( def ) , branch )
1619- }
1620-
1621- pragma [ nomagic]
1622- private predicate guardControlsSsaRead (
1623- BgInput:: Guard g , boolean branch , Definition def , ExprNode n
1624- ) {
1625- exists ( BasicBlock bb , DfInput:: Expr e |
1626- e = n .getExpr ( ) and
1627- getARead ( def ) = e and
1628- BgInput:: guardControlsBlock ( g , bb , branch ) and
1629- e .hasCfgNode ( bb , _)
1630- )
1631- }
1632-
1633- pragma [ nomagic]
1634- private predicate guardControlsPhiInput (
1635- BgInput:: Guard g , boolean branch , Definition def , BasicBlock input ,
1636- SsaInputDefinitionExt phi
1637- ) {
1638- phi .hasInputFromBlock ( def , _, _, _, input ) and
1639- (
1640- BgInput:: guardControlsBlock ( g , input , branch )
1641- or
1642- exists ( int last |
1643- last = input .length ( ) - 1 and
1644- g .hasCfgNode ( input , last ) and
1645- BgInput:: getAConditionalBasicBlockSuccessor ( input , branch ) = phi .getBasicBlock ( )
1646- )
1647- )
1648- }
1649-
1650- /** Gets a node that is safely guarded by the given guard check. */
1651- pragma [ nomagic]
1652- Node getABarrierNode ( ) {
1653- exists ( BgInput:: Guard g , boolean branch , Definition def |
1654- guardChecksSsaDef ( g , branch , def ) and
1655- guardControlsSsaRead ( g , branch , def , result )
1656- )
1657- or
1658- exists (
1659- BgInput:: Guard g , boolean branch , Definition def , BasicBlock input ,
1660- SsaInputDefinitionExt phi
1661- |
1662- guardChecksSsaDef ( g , branch , def ) and
1663- guardControlsPhiInput ( g , branch , def , input , phi ) and
1664- result .( SsaInputNode ) .isInputInto ( phi , input )
1665- )
1666- }
1667- }
1626+ /**
1627+ * Gets a node that reads SSA defininition `def`, and which is guarded by
1628+ * `g` evaluating to `branch`.
1629+ */
1630+ pragma [ nomagic]
1631+ Node getABarrierNode ( DfInput:: Guard g , Definition def , boolean branch ) {
1632+ guardControlsSsaRead ( g , branch , def , result )
1633+ or
1634+ exists ( BasicBlock input , SsaInputDefinitionExt phi |
1635+ guardControlsPhiInput ( g , branch , def , input , phi ) and
1636+ result .( SsaInputNode ) .isInputInto ( phi , input )
1637+ )
16681638 }
16691639 }
16701640}
0 commit comments