@@ -792,6 +792,10 @@ module API {
792792
793793 private predicate hasSemantics ( DataFlow:: Node nd ) { not nd .getTopLevel ( ) .isExterns ( ) }
794794
795+ bindingset [ nd]
796+ pragma [ inline_late]
797+ private predicate hasSemanticsLate ( DataFlow:: Node nd ) { hasSemantics ( nd ) }
798+
795799 private signature module StageInputSig {
796800 /** Holds if `node` should be seen as a use-node root, in addition to module imports (which are the usual roots). */
797801 predicate isAdditionalUseRoot ( Node node ) ;
@@ -1583,30 +1587,120 @@ module API {
15831587 forceLocal( Stage1:: getAPromisifiedInvocation / 3 ) ( callee , bound , succ , result )
15841588 }
15851589
1590+ private module Stage2Input implements StageInputSig {
1591+ overlay [ global]
1592+ pragma [ nomagic]
1593+ private predicate isInOverlayChangedFile ( DataFlow:: Node node ) {
1594+ overlayChangedFiles ( node .getFile ( ) .getAbsolutePath ( ) )
1595+ }
1596+
1597+ bindingset [ node]
1598+ overlay [ global]
1599+ pragma [ inline_late]
1600+ private predicate isInOverlayChangedFileLate ( DataFlow:: Node node ) {
1601+ isInOverlayChangedFile ( node )
1602+ }
1603+
1604+ /** Holds if there is a step `node1 -> node2` from an unchanged file into a changed file. */
1605+ pragma [ nomagic]
1606+ private predicate stepIntoOverlay ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
1607+ StepSummary:: step ( node1 , node2 , _) and
1608+ isInOverlayChangedFile ( node2 ) and
1609+ not isInOverlayChangedFileLate ( node1 ) and
1610+ hasSemanticsLate ( node1 )
1611+ }
1612+
1613+ /** Holds if use-node tracking starting at `nd` can reach a node in the overlay. */
1614+ pragma [ nomagic]
1615+ private predicate shouldTrackIntoOverlay ( DataFlow:: SourceNode nd ) {
1616+ exists ( DataFlow:: Node overlayNode |
1617+ stepIntoOverlay ( Stage1Local:: trackUseNodeAnyState ( nd ) , overlayNode )
1618+ )
1619+ }
1620+
1621+ /** Holds if `node` should be tracked as a use-node in stage 2. */
1622+ pragma [ nomagic]
1623+ predicate isAdditionalUseRoot ( Node node ) {
1624+ exists ( DataFlow:: Node ref |
1625+ shouldTrackIntoOverlay ( ref ) and
1626+ Stage1Local:: use ( node , ref )
1627+ )
1628+ }
1629+
1630+ /** Holds if there is a step `node1 -> node2` from a changed file into an unchanged file. */
1631+ pragma [ nomagic]
1632+ private predicate stepOutOfOverlay ( DataFlow:: Node node1 , DataFlow:: Node node2 ) {
1633+ StepSummary:: step ( node1 , node2 , _) and
1634+ isInOverlayChangedFile ( node1 ) and
1635+ not isInOverlayChangedFileLate ( node2 ) and
1636+ hasSemanticsLate ( node2 )
1637+ }
1638+
1639+ /** Holds if def-node tracking starting at `nd` can reach a node in the overlay. */
1640+ pragma [ nomagic]
1641+ private predicate shouldBacktrackIntoOverlay ( DataFlow:: Node nd ) {
1642+ exists ( DataFlow:: Node overlayNode |
1643+ stepOutOfOverlay ( overlayNode , Stage1Local:: trackDefNodeAnyState ( nd ) )
1644+ )
1645+ }
1646+
1647+ /** Holds if `node` should be tracked as a def-node in stage 2. */
1648+ pragma [ nomagic]
1649+ predicate isAdditionalDefRoot ( Node node ) {
1650+ exists ( DataFlow:: Node def |
1651+ shouldBacktrackIntoOverlay ( def ) and
1652+ Stage1Local:: rhs ( node , def )
1653+ )
1654+ }
1655+
1656+ bindingset [ node]
1657+ predicate inScope ( DataFlow:: Node node ) { isInOverlayChangedFile ( node ) }
1658+ }
1659+
1660+ private module Stage2 = Stage< Stage2Input > ;
1661+
15861662 cached
15871663 private module Cached {
15881664 cached
1589- predicate rhs ( TApiNode nd , DataFlow:: Node rhs ) { Stage1:: rhs ( nd , rhs ) }
1665+ predicate rhs ( TApiNode nd , DataFlow:: Node rhs ) {
1666+ Stage1Local:: rhs ( nd , rhs )
1667+ or
1668+ Stage2:: rhs ( nd , rhs )
1669+ }
15901670
15911671 cached
1592- predicate use ( TApiNode nd , DataFlow:: Node ref ) { Stage1:: use ( nd , ref ) }
1672+ predicate use ( TApiNode nd , DataFlow:: Node ref ) {
1673+ Stage1Local:: use ( nd , ref )
1674+ or
1675+ Stage2:: use ( nd , ref )
1676+ }
15931677
15941678 cached
15951679 DataFlow:: SourceNode trackUseNode ( DataFlow:: SourceNode nd ) {
1596- result = Stage1:: trackUseNode ( nd )
1680+ result = Stage1Local:: trackUseNode ( nd )
1681+ or
1682+ result = Stage2:: trackUseNode ( nd )
15971683 }
15981684
15991685 cached
1600- DataFlow:: SourceNode trackDefNode ( DataFlow:: Node nd ) { result = Stage1:: trackDefNode ( nd ) }
1686+ DataFlow:: SourceNode trackDefNode ( DataFlow:: Node nd ) {
1687+ result = Stage1Local:: trackDefNode ( nd )
1688+ or
1689+ result = Stage2:: trackDefNode ( nd )
1690+ }
16011691
16021692 cached
16031693 predicate edge ( TApiNode pred , Label:: ApiLabel lbl , TApiNode succ ) {
1604- Stage1:: edge ( pred , lbl , succ )
1694+ Stage1Local:: edge ( pred , lbl , succ )
1695+ or
1696+ Stage2:: edge ( pred , lbl , succ )
16051697 }
16061698
16071699 cached
16081700 DataFlow:: InvokeNode getAPromisifiedInvocation ( TApiNode callee , int bound , TApiNode succ ) {
1609- result = Stage1:: getAPromisifiedInvocation ( callee , bound , succ )
1701+ result = Stage1Local:: getAPromisifiedInvocation ( callee , bound , succ )
1702+ or
1703+ result = Stage2:: getAPromisifiedInvocation ( callee , bound , succ )
16101704 }
16111705 }
16121706
0 commit comments