@@ -127,16 +127,19 @@ private predicate sideEffectCfg(ControlFlow::Node src, ControlFlow::Node dst) {
127127
128128/**
129129 * Holds if `dominator` is the immediate dominator of `node` in
130- * the side-effect CFG.
130+ * the side-effect CFG belonging to `entry` .
131131 */
132- private predicate iDomEffect ( ControlFlow:: Node dominator , ControlFlow:: Node node ) =
133- idominance( entryNode / 1 , sideEffectCfg / 2 ) ( _, dominator , node )
132+ private predicate iDomEffect (
133+ ControlFlow:: Node entry , ControlFlow:: Node dominator , ControlFlow:: Node node
134+ ) = idominance( entryNode / 1 , sideEffectCfg / 2 ) ( entry , dominator , node )
134135
135136/**
136137 * Gets the most recent side effect. To be more precise, `result` is a
137138 * dominator of `node` and no side-effects can occur between `result` and
138139 * `node`.
139140 *
141+ * `entry` is the entry node for the function containing `node` and `result`.
142+ *
140143 * `sideEffectCFG` has an edge from the function entry to every node with a
141144 * side-effect. This means that every node with a side-effect has the
142145 * function entry as its immediate dominator. So if node `x` dominates node
@@ -180,16 +183,26 @@ private predicate iDomEffect(ControlFlow::Node dominator, ControlFlow::Node node
180183 *
181184 * The immediate dominator path to line 015 is 000 - 009 - 012 - 015.
182185 * Therefore, the most recent side effect for line 015 is line 009.
186+ * (Note that line 009 is not a side-effect itself. Instead, it is the
187+ * point where the control flow paths from the side-effects at 004 and 007
188+ * merge. Because its immediate dominator is the entry node 000, it serves
189+ * as the safe root for expressions evaluated after those side-effects.)
183190 */
184- cached
185- private ControlFlow:: Node mostRecentSideEffect ( ControlFlow:: Node node ) {
186- exists ( ControlFlow:: Node entry |
187- entryNode ( entry ) and
188- iDomEffect ( entry , result ) and
189- iDomEffect * ( result , node )
191+ private ControlFlow:: Node mostRecentSideEffect ( ControlFlow:: Node entry , ControlFlow:: Node node ) {
192+ iDomEffect ( entry , entry , result ) and
193+ result = node
194+ or
195+ exists ( ControlFlow:: Node mid |
196+ result = mostRecentSideEffect ( entry , mid ) and
197+ iDomEffect ( entry , mid , node )
190198 )
191199}
192200
201+ cached
202+ private ControlFlow:: Node mostRecentSideEffectUnique ( ControlFlow:: Node node ) {
203+ result = unique( | | mostRecentSideEffect ( _, node ) )
204+ }
205+
193206/** Used to represent the "global value number" of an expression. */
194207cached
195208private newtype GvnBase =
@@ -369,10 +382,12 @@ private predicate mkMethodAccess(DataFlow::Node access, GVN qualifier, Method m)
369382 )
370383}
371384
372- private predicate analyzableFieldRead ( Read fread , DataFlow:: Node base , Field f ) {
385+ private predicate analyzableFieldRead (
386+ Read fread , DataFlow:: Node base , Field f , ControlFlow:: Node dominator
387+ ) {
373388 exists ( IR:: ReadInstruction r | r = fread .asInstruction ( ) |
374389 r .readsField ( base .asInstruction ( ) , f ) and
375- strictcount ( mostRecentSideEffect ( r ) ) = 1 and
390+ dominator = mostRecentSideEffectUnique ( r ) and
376391 not r .isConst ( )
377392 )
378393}
@@ -381,9 +396,8 @@ private predicate mkFieldRead(
381396 DataFlow:: Node fread , GVN qualifier , Field v , ControlFlow:: Node dominator
382397) {
383398 exists ( DataFlow:: Node base |
384- analyzableFieldRead ( fread , base , v ) and
385- qualifier = globalValueNumber ( base ) and
386- dominator = mostRecentSideEffect ( fread .asInstruction ( ) )
399+ analyzableFieldRead ( fread , base , v , dominator ) and
400+ qualifier = globalValueNumber ( base )
387401 )
388402}
389403
@@ -421,18 +435,17 @@ private predicate incompleteSsa(ValueEntity v) {
421435/**
422436 * Holds if `access` is an access to a variable `target` for which SSA information is incomplete.
423437 */
424- private predicate analyzableOtherVariable ( DataFlow:: Node access , ValueEntity target ) {
438+ private predicate analyzableOtherVariable (
439+ DataFlow:: Node access , ValueEntity target , ControlFlow:: Node dominator
440+ ) {
425441 access .asInstruction ( ) .reads ( target ) and
426442 incompleteSsa ( target ) and
427- strictcount ( mostRecentSideEffect ( access .asInstruction ( ) ) ) = 1 and
443+ dominator = mostRecentSideEffectUnique ( access .asInstruction ( ) ) and
428444 not access .isConst ( ) and
429445 not target instanceof Function
430446}
431447
432- private predicate mkOtherVariable ( DataFlow:: Node access , ValueEntity x , ControlFlow:: Node dominator ) {
433- analyzableOtherVariable ( access , x ) and
434- dominator = mostRecentSideEffect ( access .asInstruction ( ) )
435- }
448+ private predicate mkOtherVariable = analyzableOtherVariable / 3 ;
436449
437450private predicate analyzableBinaryOp (
438451 DataFlow:: BinaryOperationNode op , string opname , DataFlow:: Node lhs , DataFlow:: Node rhs
@@ -463,29 +476,29 @@ private predicate mkUnaryOp(DataFlow::UnaryOperationNode op, GVN child, string o
463476 opname = op .getOperator ( )
464477}
465478
466- private predicate analyzableIndexExpr ( DataFlow:: ElementReadNode ae ) {
467- strictcount ( mostRecentSideEffect ( ae .asInstruction ( ) ) ) = 1 and
479+ private predicate analyzableIndexExpr ( DataFlow:: ElementReadNode ae , ControlFlow :: Node dominator ) {
480+ dominator = mostRecentSideEffectUnique ( ae .asInstruction ( ) ) and
468481 not ae .isConst ( )
469482}
470483
471484private predicate mkIndex (
472485 DataFlow:: ElementReadNode ae , GVN base , GVN offset , ControlFlow:: Node dominator
473486) {
474- analyzableIndexExpr ( ae ) and
487+ analyzableIndexExpr ( ae , dominator ) and
475488 base = globalValueNumber ( ae .getBase ( ) ) and
476- offset = globalValueNumber ( ae .getIndex ( ) ) and
477- dominator = mostRecentSideEffect ( ae .asInstruction ( ) )
489+ offset = globalValueNumber ( ae .getIndex ( ) )
478490}
479491
480- private predicate analyzablePointerDereferenceExpr ( DataFlow:: PointerDereferenceNode deref ) {
481- strictcount ( mostRecentSideEffect ( deref .asInstruction ( ) ) ) = 1 and
492+ private predicate analyzablePointerDereferenceExpr (
493+ DataFlow:: PointerDereferenceNode deref , ControlFlow:: Node dominator
494+ ) {
495+ dominator = mostRecentSideEffectUnique ( deref .asInstruction ( ) ) and
482496 not deref .isConst ( )
483497}
484498
485499private predicate mkDeref ( DataFlow:: PointerDereferenceNode deref , GVN p , ControlFlow:: Node dominator ) {
486- analyzablePointerDereferenceExpr ( deref ) and
487- p = globalValueNumber ( deref .getOperand ( ) ) and
488- dominator = mostRecentSideEffect ( deref .asInstruction ( ) )
500+ analyzablePointerDereferenceExpr ( deref , dominator ) and
501+ p = globalValueNumber ( deref .getOperand ( ) )
489502}
490503
491504private predicate ssaInit ( SsaExplicitDefinition ssa , DataFlow:: Node rhs ) {
@@ -587,12 +600,12 @@ private predicate analyzableExpr(DataFlow::Node e) {
587600 analyzableConst ( e ) or
588601 any ( DataFlow:: SsaNode ssa ) .getAUse ( ) = e or
589602 e instanceof DataFlow:: SsaNode or
590- analyzableOtherVariable ( e , _) or
603+ analyzableOtherVariable ( e , _, _ ) or
591604 analyzableMethodAccess ( e , _, _) or
592- analyzableFieldRead ( e , _, _) or
605+ analyzableFieldRead ( e , _, _, _ ) or
593606 analyzableCall ( e , _) or
594607 analyzableBinaryOp ( e , _, _, _) or
595608 analyzableUnaryOp ( e ) or
596- analyzableIndexExpr ( e ) or
597- analyzablePointerDereferenceExpr ( e )
609+ analyzableIndexExpr ( e , _ ) or
610+ analyzablePointerDereferenceExpr ( e , _ )
598611}
0 commit comments