@@ -657,19 +657,9 @@ class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
657
657
*/
658
658
predicate adjacentDefRead ( IRBlock bb1 , int i1 , SourceVariable sv , IRBlock bb2 , int i2 ) {
659
659
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
- )
665
660
}
666
661
667
662
predicate 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
673
663
exists ( UseImpl use |
674
664
use .hasIndexInBlock ( bb , i , sv ) and
675
665
nodeTo = use .getNode ( )
@@ -735,25 +725,14 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
735
725
}
736
726
737
727
/**
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)`.
751
730
*/
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
757
736
)
758
737
}
759
738
@@ -768,10 +747,14 @@ private predicate adjustForPointerArith(PostUpdateNode pun, SourceVariable sv, I
768
747
private predicate ssaFlowImpl (
769
748
IRBlock bb1 , int i1 , SourceVariable sv , Node nodeFrom , Node nodeTo , boolean uncertain
770
749
) {
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 )
775
758
) and
776
759
nodeFrom != nodeTo
777
760
}
@@ -780,7 +763,7 @@ private predicate ssaFlowImpl(
780
763
private Node getAPriorDefinition ( DefinitionExt next ) {
781
764
exists ( IRBlock bb , int i , SourceVariable sv |
782
765
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
784
767
nodeToDefOrUse ( result , sv , bb , i , _)
785
768
)
786
769
}
@@ -887,9 +870,32 @@ private predicate isArgumentOfCallable(DataFlowCall call, Node n) {
887
870
* Holds if there is use-use flow from `pun`'s pre-update node to `n`.
888
871
*/
889
872
private 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 )
893
899
)
894
900
}
895
901
@@ -944,11 +950,16 @@ predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
944
950
945
951
/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */
946
952
predicate 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 |
948
954
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 )
952
963
)
953
964
}
954
965
@@ -1022,12 +1033,16 @@ module SsaCached {
1022
1033
* Holds if the node at index `i` in `bb` is a last reference to SSA definition
1023
1034
* `def`. The reference is last because it can reach another write `next`,
1024
1035
* 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`.
1025
1040
*/
1026
1041
cached
1027
1042
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
1029
1044
) {
1030
- SsaImpl:: lastRefRedefExt ( def , sv , bb , i , next )
1045
+ SsaImpl:: lastRefRedefExt ( def , sv , bb , i , input , next )
1031
1046
}
1032
1047
1033
1048
cached
@@ -1191,7 +1206,7 @@ class Phi extends TPhi, SsaDef {
1191
1206
1192
1207
override string toString ( ) { result = phi .toString ( ) }
1193
1208
1194
- SsaPhiNode getNode ( ) { result .getPhiNode ( ) = phi }
1209
+ SsaPhiInputNode getNode ( IRBlock block ) { result .getPhiNode ( ) = phi and result . getBlock ( ) = block }
1195
1210
1196
1211
predicate hasInputFromBlock ( Definition inp , IRBlock bb ) { inp = phiHasInputFromBlockExt ( phi , bb ) }
1197
1212
@@ -1200,6 +1215,23 @@ class Phi extends TPhi, SsaDef {
1200
1215
1201
1216
private module SsaImpl = SsaImplCommon:: Make< Location , SsaInput > ;
1202
1217
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
+
1203
1235
/**
1204
1236
* An static single assignment (SSA) phi node.
1205
1237
*
@@ -1219,13 +1251,21 @@ class PhiNode extends SsaImpl::DefinitionExt {
1219
1251
*/
1220
1252
predicate isPhiRead ( ) { this instanceof SsaImpl:: PhiReadNode }
1221
1253
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 )
1225
1265
}
1226
1266
1227
1267
/** 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 , _, _ , _ , _ ) }
1229
1269
}
1230
1270
1231
1271
/** An static single assignment (SSA) definition. */
@@ -1240,6 +1280,15 @@ class DefinitionExt extends SsaImpl::DefinitionExt {
1240
1280
result = this .getAPhiInputOrPriorDefinition * ( ) and
1241
1281
not result instanceof PhiNode
1242
1282
}
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
+ }
1243
1292
}
1244
1293
1245
1294
class Definition = SsaImpl:: Definition ;
0 commit comments