@@ -657,19 +657,9 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
657657 */
658658predicate adjacentDefRead ( IRBlock bb1 , int i1 , SourceVariable sv , IRBlock bb2 , int i2 ) {
659659 adjacentDefReadExt ( _, sv , bb1 , i1 , bb2 , i2 )
660- or
661- exists ( PhiNode phi |
662- lastRefRedefExt ( _, sv , bb1 , i1 , phi ) and
663- phi .definesAt ( sv , bb2 , i2 , _)
664- )
665660}
666661
667662predicate useToNode ( IRBlock bb , int i , SourceVariable sv , Node nodeTo ) {
668- exists ( Phi phi |
669- phi .asPhi ( ) .definesAt ( sv , bb , i , _) and
670- nodeTo = phi .getNode ( )
671- )
672- or
673663 exists ( UseImpl use |
674664 use .hasIndexInBlock ( bb , i , sv ) and
675665 nodeTo = use .getNode ( )
@@ -735,25 +725,14 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
735725}
736726
737727/**
738- * The reason for this predicate is a bit annoying:
739- * We cannot mark a `PointerArithmeticInstruction` that computes an offset based on some SSA
740- * variable `x` as a use of `x` since this creates taint-flow in the following example:
741- * ```c
742- * int x = array[source]
743- * sink(*array)
744- * ```
745- * This is because `source` would flow from the operand of `PointerArithmeticInstruction` to the
746- * result of the instruction, and into the `IndirectOperand` that represents the value of `*array`.
747- * Then, via use-use flow, flow will arrive at `*array` in `sink(*array)`.
748- *
749- * So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
750- * first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
728+ * Holds if `node` is a phi input node that should receive flow from the
729+ * definition to (or use of) `sv` at `(bb1, i1)`.
751730 */
752- private predicate adjustForPointerArith ( PostUpdateNode pun , SourceVariable sv , IRBlock bb2 , int i2 ) {
753- exists ( IRBlock bb1 , int i1 , Node adjusted |
754- indirectConversionFlowStep * ( adjusted , pun . getPreUpdateNode ( ) ) and
755- nodeToDefOrUse ( adjusted , sv , bb1 , i1 , _ ) and
756- adjacentDefRead ( bb1 , i1 , sv , bb2 , i2 )
731+ private predicate phiToNode ( SsaPhiInputNode node , SourceVariable sv , IRBlock bb1 , int i1 ) {
732+ exists ( PhiNode phi , IRBlock input |
733+ phi . hasInputFromBlock ( _ , sv , bb1 , i1 , input ) and
734+ node . getPhiNode ( ) = phi and
735+ node . getBlock ( ) = input
757736 )
758737}
759738
@@ -768,10 +747,14 @@ private predicate adjustForPointerArith(PostUpdateNode pun, SourceVariable sv, I
768747private predicate ssaFlowImpl (
769748 IRBlock bb1 , int i1 , SourceVariable sv , Node nodeFrom , Node nodeTo , boolean uncertain
770749) {
771- exists ( IRBlock bb2 , int i2 |
772- nodeToDefOrUse ( nodeFrom , sv , bb1 , i1 , uncertain ) and
773- adjacentDefRead ( bb1 , i1 , sv , bb2 , i2 ) and
774- useToNode ( bb2 , i2 , sv , nodeTo )
750+ nodeToDefOrUse ( nodeFrom , sv , bb1 , i1 , uncertain ) and
751+ (
752+ exists ( IRBlock bb2 , int i2 |
753+ adjacentDefRead ( bb1 , i1 , sv , bb2 , i2 ) and
754+ useToNode ( bb2 , i2 , sv , nodeTo )
755+ )
756+ or
757+ phiToNode ( nodeTo , sv , bb1 , i1 )
775758 ) and
776759 nodeFrom != nodeTo
777760}
@@ -780,7 +763,7 @@ private predicate ssaFlowImpl(
780763private Node getAPriorDefinition ( DefinitionExt next ) {
781764 exists ( IRBlock bb , int i , SourceVariable sv |
782765 lastRefRedefExt ( _, pragma [ only_bind_into ] ( sv ) , pragma [ only_bind_into ] ( bb ) ,
783- pragma [ only_bind_into ] ( i ) , next ) and
766+ pragma [ only_bind_into ] ( i ) , _ , next ) and
784767 nodeToDefOrUse ( result , sv , bb , i , _)
785768 )
786769}
@@ -887,9 +870,32 @@ private predicate isArgumentOfCallable(DataFlowCall call, Node n) {
887870 * Holds if there is use-use flow from `pun`'s pre-update node to `n`.
888871 */
889872private predicate postUpdateNodeToFirstUse ( PostUpdateNode pun , Node n ) {
890- exists ( SourceVariable sv , IRBlock bb2 , int i2 |
891- adjustForPointerArith ( pun , sv , bb2 , i2 ) and
892- useToNode ( bb2 , i2 , sv , n )
873+ // The reason for this predicate is a bit annoying:
874+ // We cannot mark a `PointerArithmeticInstruction` that computes an offset
875+ // based on some SSA
876+ // variable `x` as a use of `x` since this creates taint-flow in the
877+ // following example:
878+ // ```c
879+ // int x = array[source]
880+ // sink(*array)
881+ // ```
882+ // This is because `source` would flow from the operand of `PointerArithmetic`
883+ // instruction to the result of the instruction, and into the `IndirectOperand`
884+ // that represents the value of `*array`. Then, via use-use flow, flow will
885+ // arrive at `*array` in `sink(*array)`.
886+ // So this predicate recurses back along conversions and `PointerArithmetic`
887+ // instructions to find the first use that has provides use-use flow, and
888+ // uses that target as the target of the `nodeFrom`.
889+ exists ( Node adjusted , IRBlock bb1 , int i1 , SourceVariable sv |
890+ indirectConversionFlowStep * ( adjusted , pun .getPreUpdateNode ( ) ) and
891+ useToNode ( bb1 , i1 , sv , adjusted )
892+ |
893+ exists ( IRBlock bb2 , int i2 |
894+ adjacentDefRead ( bb1 , i1 , sv , bb2 , i2 ) and
895+ useToNode ( bb2 , i2 , sv , n )
896+ )
897+ or
898+ phiToNode ( n , sv , bb1 , i1 )
893899 )
894900}
895901
@@ -944,11 +950,16 @@ predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
944950
945951/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */
946952predicate fromPhiNode ( SsaPhiNode nodeFrom , Node nodeTo ) {
947- exists ( PhiNode phi , SourceVariable sv , IRBlock bb1 , int i1 , IRBlock bb2 , int i2 |
953+ exists ( PhiNode phi , SourceVariable sv , IRBlock bb1 , int i1 |
948954 phi = nodeFrom .getPhiNode ( ) and
949- phi .definesAt ( sv , bb1 , i1 , _) and
950- adjacentDefRead ( bb1 , i1 , sv , bb2 , i2 ) and
951- useToNode ( bb2 , i2 , sv , nodeTo )
955+ phi .definesAt ( sv , bb1 , i1 , _)
956+ |
957+ exists ( IRBlock bb2 , int i2 |
958+ adjacentDefRead ( bb1 , i1 , sv , bb2 , i2 ) and
959+ useToNode ( bb2 , i2 , sv , nodeTo )
960+ )
961+ or
962+ phiToNode ( nodeTo , sv , bb1 , i1 )
952963 )
953964}
954965
@@ -1022,12 +1033,16 @@ module SsaCached {
10221033 * Holds if the node at index `i` in `bb` is a last reference to SSA definition
10231034 * `def`. The reference is last because it can reach another write `next`,
10241035 * without passing through another read or write.
1036+ *
1037+ * The path from node `i` in `bb` to `next` goes via basic block `input`,
1038+ * which is either a predecessor of the basic block of `next`, or `input` =
1039+ * `bb` in case `next` occurs in basic block `bb`.
10251040 */
10261041 cached
10271042 predicate lastRefRedefExt (
1028- DefinitionExt def , SourceVariable sv , IRBlock bb , int i , DefinitionExt next
1043+ DefinitionExt def , SourceVariable sv , IRBlock bb , int i , IRBlock input , DefinitionExt next
10291044 ) {
1030- SsaImpl:: lastRefRedefExt ( def , sv , bb , i , next )
1045+ SsaImpl:: lastRefRedefExt ( def , sv , bb , i , input , next )
10311046 }
10321047
10331048 cached
@@ -1191,7 +1206,7 @@ class Phi extends TPhi, SsaDef {
11911206
11921207 override string toString ( ) { result = phi .toString ( ) }
11931208
1194- SsaPhiNode getNode ( ) { result .getPhiNode ( ) = phi }
1209+ SsaPhiInputNode getNode ( IRBlock block ) { result .getPhiNode ( ) = phi and result . getBlock ( ) = block }
11951210
11961211 predicate hasInputFromBlock ( Definition inp , IRBlock bb ) { inp = phiHasInputFromBlockExt ( phi , bb ) }
11971212
@@ -1200,6 +1215,23 @@ class Phi extends TPhi, SsaDef {
12001215
12011216private module SsaImpl = SsaImplCommon:: Make< Location , SsaInput > ;
12021217
1218+ /**
1219+ * An static single assignment (SSA) definition that is used as an input to a
1220+ * phi or phi-read node.
1221+ */
1222+ class PhiInputNodeExt extends SsaImpl:: DefinitionExt {
1223+ PhiNode phi ;
1224+
1225+ PhiInputNodeExt ( ) { this = SsaCached:: phiHasInputFromBlockExt ( phi , _) }
1226+
1227+ /** Gets the phi or phi-read node that receives this node as input. */
1228+ PhiNode getPhi ( ) { result = phi }
1229+
1230+ predicate hasInputFromBlock ( DefinitionExt def , IRBlock input ) {
1231+ SsaCached:: lastRefRedefExt ( def , _, _, _, input , this )
1232+ }
1233+ }
1234+
12031235/**
12041236 * An static single assignment (SSA) phi node.
12051237 *
@@ -1219,13 +1251,21 @@ class PhiNode extends SsaImpl::DefinitionExt {
12191251 */
12201252 predicate isPhiRead ( ) { this instanceof SsaImpl:: PhiReadNode }
12211253
1222- /** Holds if `inp` is an input to this phi node along the edge originating in `bb`. */
1223- predicate hasInputFromBlock ( Definition inp , IRBlock bb ) {
1224- inp = SsaCached:: phiHasInputFromBlockExt ( this , bb )
1254+ /**
1255+ * Holds if the node at index `i` in `bb` is a last reference to SSA
1256+ * definition `def` of `sv`. The reference is last because it can reach
1257+ * this phi node, without passing through another read or write.
1258+ *
1259+ * The path from node `i` in `bb` to this phi node goes via basic block
1260+ * `input`, which is either a predecessor of the basic block of this phi
1261+ * node, or `input` = `bb` in case this phi node occurs in basic block `bb`.
1262+ */
1263+ predicate hasInputFromBlock ( DefinitionExt def , SourceVariable sv , IRBlock bb , int i , IRBlock input ) {
1264+ SsaCached:: lastRefRedefExt ( def , sv , bb , i , input , this )
12251265 }
12261266
12271267 /** Gets a definition that is an input to this phi node. */
1228- final Definition getAnInput ( ) { this .hasInputFromBlock ( result , _) }
1268+ final Definition getAnInput ( ) { this .hasInputFromBlock ( result , _, _ , _ , _ ) }
12291269}
12301270
12311271/** An static single assignment (SSA) definition. */
@@ -1240,6 +1280,15 @@ class DefinitionExt extends SsaImpl::DefinitionExt {
12401280 result = this .getAPhiInputOrPriorDefinition * ( ) and
12411281 not result instanceof PhiNode
12421282 }
1283+
1284+ /** Gets a node that represents a read of this SSA definition. */
1285+ Node getARead ( ) {
1286+ exists ( SourceVariable sv , IRBlock bb , int i | SsaCached:: ssaDefReachesReadExt ( sv , this , bb , i ) |
1287+ useToNode ( bb , i , sv , result )
1288+ or
1289+ phiToNode ( result , sv , bb , i )
1290+ )
1291+ }
12431292}
12441293
12451294class Definition = SsaImpl:: Definition ;
0 commit comments