@@ -383,6 +383,14 @@ private module CachedSteps {
383383 result = DataFlow:: valueNode ( gv .getAnAccess ( ) )
384384 }
385385
386+ /**
387+ * Gets a post-update of `gv` in `f`.
388+ */
389+ pragma [ noinline]
390+ private DataFlow:: ExprPostUpdateNode getAPostUpdateIn ( GlobalVariable gv , File f ) {
391+ result .getPreUpdateNode ( ) = getAUseIn ( gv , f )
392+ }
393+
386394 /**
387395 * Holds if there is a flow step from `pred` to `succ` through a global
388396 * variable. Both `pred` and `succ` must be in the same file.
@@ -395,6 +403,20 @@ private module CachedSteps {
395403 )
396404 }
397405
406+ /**
407+ * Holds if `pred` is a post-update node for a use of a global variable, and `succ`
408+ * is a use of the global variable in the same file.
409+ */
410+ cached
411+ predicate globalPostUpdateStep ( DataFlow:: Node pred , DataFlow:: Node succ ) {
412+ exists ( GlobalVariable gv , File f |
413+ pred = getAPostUpdateIn ( gv , f ) and
414+ succ = getAUseIn ( gv , f ) and
415+ // Remove some unnecessary steps
416+ not succ = any ( DataFlow:: PropWrite write ) .getBase ( )
417+ )
418+ }
419+
398420 /**
399421 * Holds if there is a write to property `prop` of global variable `gv`
400422 * in file `f`, where the right-hand side of the write is `rhs`.
@@ -438,6 +460,7 @@ private module CachedSteps {
438460 predicate basicStoreStep ( DataFlow:: Node pred , DataFlow:: Node succ , string prop ) {
439461 succ .( DataFlow:: SourceNode ) .hasPropertyWrite ( prop , pred )
440462 or
463+ // Note that this case is handled by globalPostUpdateStep in dataflow2
441464 exists ( GlobalVariable gv , File f |
442465 globalPropertyWrite ( gv , f , prop , pred ) and
443466 globalPropertyRead ( gv , f , prop , succ )
0 commit comments