@@ -132,61 +132,70 @@ predicate maybeAssignsAccessedPropInBlock(DataFlow::PropWrite assign, boolean af
132132 or
133133 // impure expression that might access the property before/after assign
134134 exists ( ReachableBasicBlock block | assign .getWriteNode ( ) .getBasicBlock ( ) = block |
135- after = true and isBeforeImpure ( assign , block )
135+ after = true and PurityCheck :: isBeforeImpure ( assign , block )
136136 or
137- after = false and isAfterImpure ( assign , block )
137+ after = false and PurityCheck :: isAfterImpure ( assign , block )
138138 )
139139 )
140140}
141141
142142/**
143- * Holds if a ControlFlowNode `c` is before an impure expression inside `bb` .
143+ * Predicates to check if a property-write comes after/ before an impure expression within the same basicblock .
144144 */
145- predicate isBeforeImpure ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
146- getANodeAfterWrite ( write , bb ) .( Expr ) .isImpure ( )
147- }
145+ private module PurityCheck {
146+ /**
147+ * Holds if a ControlFlowNode `c` is before an impure expression inside `bb`.
148+ */
149+ predicate isBeforeImpure ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
150+ getANodeAfterWrite ( write , bb ) .( Expr ) .isImpure ( )
151+ }
148152
149- /**
150- * Gets a ControlFlowNode that comes after `write` inside `bb`.
151- * Stops after finding the first impure expression
152- */
153- ControlFlowNode getANodeAfterWrite ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
154- // base case
155- result .getBasicBlock ( ) = bb and
156- postDominatedPropWrite ( _, write , _, false ) and // early pruning - manual magic
157- result = write .getWriteNode ( ) .getASuccessor ( )
158- or
159- // recursive case
160- exists ( ControlFlowNode prev | prev = getANodeAfterWrite ( write , bb ) |
161- not result instanceof BasicBlock and
162- not prev .( Expr ) .isImpure ( ) and
163- result = prev .getASuccessor ( )
164- )
165- }
153+ /**
154+ * Gets a ControlFlowNode that comes after `write` inside `bb`.
155+ * Stops after finding the first impure expression.
156+ *
157+ * This predicate is used as a helper to check if one of the successors to `write` inside `bb` is impure (see `isBeforeImpure`).
158+ */
159+ private ControlFlowNode getANodeAfterWrite ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
160+ // base case
161+ result .getBasicBlock ( ) = bb and
162+ postDominatedPropWrite ( _, write , _, false ) and // early pruning - manual magic
163+ result = write .getWriteNode ( ) .getASuccessor ( )
164+ or
165+ // recursive case
166+ exists ( ControlFlowNode prev | prev = getANodeAfterWrite ( write , bb ) |
167+ not result instanceof BasicBlock and
168+ not prev .( Expr ) .isImpure ( ) and
169+ result = prev .getASuccessor ( )
170+ )
171+ }
166172
167- /**
168- * Holds if a ControlFlowNode `c` is after an impure expression inside `bb`.
169- */
170- predicate isAfterImpure ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
171- getANodeBeforeWrite ( write , bb ) .( Expr ) .isImpure ( )
172- }
173+ /**
174+ * Holds if a ControlFlowNode `c` is after an impure expression inside `bb`.
175+ */
176+ predicate isAfterImpure ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
177+ getANodeBeforeWrite ( write , bb ) .( Expr ) .isImpure ( )
178+ }
173179
174- /**
175- * Gets a ControlFlowNode that comes before `write` inside `bb`.
176- * Stops after finding the first impure expression.
177- */
178- ControlFlowNode getANodeBeforeWrite ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
179- // base case
180- result .getBasicBlock ( ) = bb and
181- postDominatedPropWrite ( _, _, write , false ) and // early pruning - manual magic
182- result = write .getWriteNode ( ) .getAPredecessor ( )
183- or
184- // recursive case
185- exists ( ControlFlowNode prev | prev = getANodeBeforeWrite ( write , bb ) |
186- not prev instanceof BasicBlock and
187- not prev .( Expr ) .isImpure ( ) and
188- result = prev .getAPredecessor ( )
189- )
180+ /**
181+ * Gets a ControlFlowNode that comes before `write` inside `bb`.
182+ * Stops after finding the first impure expression.
183+ *
184+ * This predicate is used as a helper to check if one of the predecessors to `write` inside `bb` is impure (see `isAfterImpure`).
185+ */
186+ private ControlFlowNode getANodeBeforeWrite ( DataFlow:: PropWrite write , ReachableBasicBlock bb ) {
187+ // base case
188+ result .getBasicBlock ( ) = bb and
189+ postDominatedPropWrite ( _, _, write , false ) and // early pruning - manual magic
190+ result = write .getWriteNode ( ) .getAPredecessor ( )
191+ or
192+ // recursive case
193+ exists ( ControlFlowNode prev | prev = getANodeBeforeWrite ( write , bb ) |
194+ not prev instanceof BasicBlock and
195+ not prev .( Expr ) .isImpure ( ) and
196+ result = prev .getAPredecessor ( )
197+ )
198+ }
190199}
191200
192201/**
0 commit comments