Skip to content

Commit f7774ef

Browse files
yoffCopilot
andcommitted
Bind explicit CFG successors before expansion
Late-inline the explicit-step after-value wrapper so AST and successor demand are bound before expanding control-flow nodes, without changing CFG semantics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 529363f5-bc7d-4f0b-9f47-e03ba9aa0cdf
1 parent 6cf214c commit f7774ef

1 file changed

Lines changed: 52 additions & 34 deletions

File tree

‎shared/controlflow/codeql/controlflow/ControlFlowGraph.qll‎

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,6 +1468,14 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
14681468
else result.isAdditional(catch, catchClauseEmptyBodyTag())
14691469
}
14701470

1471+
bindingset[ast, successor]
1472+
pragma[inline_late]
1473+
private predicate explicitAfterValue(
1474+
PreControlFlowNode node, AstNode ast, ConditionalSuccessor successor
1475+
) {
1476+
node.isAfterValue(ast, successor)
1477+
}
1478+
14711479
/** Holds if there is a local non-abrupt step from `n1` to `n2`. */
14721480
private predicate explicitStep(PreControlFlowNode n1, PreControlFlowNode n2) {
14731481
Input2::step(n1, n2)
@@ -1478,7 +1486,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
14781486
or
14791487
exists(CallableContextOption ctx, Parameter p, int i | p = getRankedParameter(c, ctx, i) |
14801488
exists(MatchingSuccessor t |
1481-
n1.isAfterValue(p.getPattern(), t) and
1489+
explicitAfterValue(n1, p.getPattern(), t) and
14821490
if t.isMatch()
14831491
then n2.isBefore(getParameterPatternOrBodyEntry(c, ctx, i + 1))
14841492
else n2.isBefore(p.getDefaultValue())
@@ -1503,8 +1511,8 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15031511
exists(AstNode child, AstNode parent | propagatesValue(child, parent) |
15041512
exists(ConditionalSuccessor t |
15051513
inConditionalContext(parent, t.getKind()) and
1506-
n1.isAfterValue(child, t) and
1507-
n2.isAfterValue(parent, t)
1514+
explicitAfterValue(n1, child, t) and
1515+
explicitAfterValue(n2, parent, t)
15081516
)
15091517
or
15101518
not inConditionalContext(parent, _) and
@@ -1518,11 +1526,11 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15181526
n1.isBefore(binexpr) and
15191527
n2.isBefore(binexpr.getLeftOperand())
15201528
or
1521-
n1.isAfterValue(binexpr.getLeftOperand(), shortcircuitValue.getDual()) and
1529+
explicitAfterValue(n1, binexpr.getLeftOperand(), shortcircuitValue.getDual()) and
15221530
n2.isBefore(binexpr.getRightOperand())
15231531
or
1524-
n1.isAfterValue(binexpr.getLeftOperand(), shortcircuitValue) and
1525-
n2.isAfterValue(binexpr, shortcircuitValue)
1532+
explicitAfterValue(n1, binexpr.getLeftOperand(), shortcircuitValue) and
1533+
explicitAfterValue(n2, binexpr, shortcircuitValue)
15261534
or
15271535
// short-circuiting operations with side-effects (e.g. `x &&= y`) are in post-order:
15281536
n1.isAfter(binexpr.getRightOperand()) and
@@ -1537,19 +1545,21 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15371545
n2.isBefore(notexpr.getOperand())
15381546
or
15391547
exists(BooleanSuccessor t |
1540-
n1.isAfterValue(notexpr.getOperand(), t) and
1541-
n2.isAfterValue(notexpr, t.getDual())
1548+
explicitAfterValue(n1, notexpr.getOperand(), t) and
1549+
explicitAfterValue(n2, notexpr, t.getDual())
15421550
)
15431551
)
15441552
or
15451553
exists(ConditionalExpr condexpr |
15461554
n1.isBefore(condexpr) and
15471555
n2.isBefore(condexpr.getCondition())
15481556
or
1549-
n1.isAfterTrue(condexpr.getCondition()) and
1557+
explicitAfterValue(n1, condexpr.getCondition(),
1558+
any(BooleanSuccessor b | b.getValue() = true)) and
15501559
n2.isBefore(condexpr.getThen())
15511560
or
1552-
n1.isAfterFalse(condexpr.getCondition()) and
1561+
explicitAfterValue(n1, condexpr.getCondition(),
1562+
any(BooleanSuccessor b | b.getValue() = false)) and
15531563
n2.isBefore(condexpr.getElse())
15541564
)
15551565
or
@@ -1561,7 +1571,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15611571
n2.isIn(pme)
15621572
or
15631573
n1.isIn(pme) and
1564-
n2.isAfterValue(pme, any(BooleanSuccessor s | s.getValue() = false))
1574+
explicitAfterValue(n2, pme, any(BooleanSuccessor s | s.getValue() = false))
15651575
or
15661576
n1.isIn(pme) and
15671577
n2.isAdditional(pme, patternMatchTrueTag())
@@ -1570,7 +1580,7 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15701580
n2.isBefore(pme.getPattern())
15711581
or
15721582
n1.isAfter(pme.getPattern()) and
1573-
n2.isAfterValue(pme, any(BooleanSuccessor s | s.getValue() = true))
1583+
explicitAfterValue(n2, pme, any(BooleanSuccessor s | s.getValue() = true))
15741584
)
15751585
or
15761586
exists(IfStmt ifstmt |
@@ -1584,15 +1594,17 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15841594
n1.isAfter(getIfInit(ifstmt)) and
15851595
n2.isBefore(ifstmt.getCondition())
15861596
or
1587-
n1.isAfterTrue(ifstmt.getCondition()) and
1597+
explicitAfterValue(n1, ifstmt.getCondition(),
1598+
any(BooleanSuccessor b | b.getValue() = true)) and
15881599
(
15891600
n2.isBefore(ifstmt.getThen())
15901601
or
15911602
not exists(ifstmt.getThen()) and
15921603
n2.isAfter(ifstmt)
15931604
)
15941605
or
1595-
n1.isAfterFalse(ifstmt.getCondition()) and
1606+
explicitAfterValue(n1, ifstmt.getCondition(),
1607+
any(BooleanSuccessor b | b.getValue() = false)) and
15961608
(
15971609
n2.isBefore(ifstmt.getElse())
15981610
or
@@ -1627,10 +1639,10 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
16271639
n1.isAdditional(loopstmt, loopHeaderTag()) and
16281640
n2.isBefore(cond)
16291641
or
1630-
n1.isAfterValue(cond, any(BooleanSuccessor b | b.getValue() = while)) and
1642+
explicitAfterValue(n1, cond, any(BooleanSuccessor b | b.getValue() = while)) and
16311643
n2.isBefore(loopstmt.getBody())
16321644
or
1633-
n1.isAfterValue(cond, any(BooleanSuccessor b | b.getValue() = while.booleanNot())) and
1645+
explicitAfterValue(n1, cond, any(BooleanSuccessor b | b.getValue() = while.booleanNot())) and
16341646
(
16351647
n2.isBefore(getLoopElse(loopstmt))
16361648
or
@@ -1650,15 +1662,15 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
16501662
n1.isBefore(foreachstmt) and
16511663
n2.isBefore(foreachstmt.getCollection())
16521664
or
1653-
n1.isAfterValue(foreachstmt.getCollection(),
1665+
explicitAfterValue(n1, foreachstmt.getCollection(),
16541666
any(EmptinessSuccessor t | t.getValue() = true)) and
16551667
(
16561668
n2.isBefore(getLoopElse(foreachstmt))
16571669
or
16581670
not exists(getLoopElse(foreachstmt)) and n2.isAfter(foreachstmt)
16591671
)
16601672
or
1661-
n1.isAfterValue(foreachstmt.getCollection(),
1673+
explicitAfterValue(n1, foreachstmt.getCollection(),
16621674
any(EmptinessSuccessor t | t.getValue() = false)) and
16631675
n2.isBefore(foreachstmt.getVariable())
16641676
or
@@ -1699,10 +1711,12 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
16991711
not exists(forstmt.getInit(i + 1)) and n2 = condentry
17001712
)
17011713
or
1702-
n1.isAfterTrue(forstmt.getCondition()) and
1714+
explicitAfterValue(n1, forstmt.getCondition(),
1715+
any(BooleanSuccessor b | b.getValue() = true)) and
17031716
n2.isBefore(forstmt.getBody())
17041717
or
1705-
n1.isAfterFalse(forstmt.getCondition()) and
1718+
explicitAfterValue(n1, forstmt.getCondition(),
1719+
any(BooleanSuccessor b | b.getValue() = false)) and
17061720
n2.isAfter(forstmt)
17071721
or
17081722
n1.isAfter(forstmt.getBody()) and
@@ -1764,7 +1778,8 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
17641778
n2.isAfter(trystmt)
17651779
or
17661780
exists(int i |
1767-
n1.isAfterValue(trystmt.getCatch(i), any(MatchingSuccessor t | t.getValue() = false)) and
1781+
explicitAfterValue(n1, trystmt.getCatch(i),
1782+
any(MatchingSuccessor t | t.getValue() = false)) and
17681783
n2.isBefore(trystmt.getCatch(i + 1))
17691784
)
17701785
)
@@ -1795,22 +1810,24 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
17951810
n2 = beforePattern
17961811
or
17971812
exists(MatchingSuccessor t |
1798-
n1.isAfterValue(catchclause.getPattern(), t) and
1799-
if t.isMatch() then n2 = beforeVar else n2.isAfterValue(catchclause, t)
1813+
explicitAfterValue(n1, catchclause.getPattern(), t) and
1814+
if t.isMatch() then n2 = beforeVar else explicitAfterValue(n2, catchclause, t)
18001815
)
18011816
or
1802-
n1.isAfterValue(catchclause, any(MatchingSuccessor t | t.getValue() = true)) and
1817+
explicitAfterValue(n1, catchclause, any(MatchingSuccessor t | t.getValue() = true)) and
18031818
n2 = beforeVar
18041819
or
18051820
n1.isAfter(catchclause.getVariable()) and
18061821
n2 = beforeCond
18071822
)
18081823
or
1809-
n1.isAfterTrue(catchclause.getCondition()) and
1824+
explicitAfterValue(n1, catchclause.getCondition(),
1825+
any(BooleanSuccessor b | b.getValue() = true)) and
18101826
n2 = getBeforeCatchBody(catchclause)
18111827
or
1812-
n1.isAfterFalse(catchclause.getCondition()) and
1813-
n2.isAfterValue(catchclause, any(MatchingSuccessor t | t.getValue() = false))
1828+
explicitAfterValue(n1, catchclause.getCondition(),
1829+
any(BooleanSuccessor b | b.getValue() = false)) and
1830+
explicitAfterValue(n2, catchclause, any(MatchingSuccessor t | t.getValue() = false))
18141831
)
18151832
or
18161833
exists(Switch switch, PreControlFlowNode firstCase |
@@ -1829,10 +1846,11 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
18291846
n2 = firstCase
18301847
or
18311848
exists(int i |
1832-
n1.isAfterValue(getRankedCaseCfgOrder(switch, i),
1849+
explicitAfterValue(n1, getRankedCaseCfgOrder(switch, i),
18331850
any(MatchingSuccessor t | t.getValue() = false))
18341851
or
1835-
n1.isAfterFalse(getRankedCaseCfgOrder(switch, i).getGuard())
1852+
explicitAfterValue(n1, getRankedCaseCfgOrder(switch, i).getGuard(),
1853+
any(BooleanSuccessor b | b.getValue() = false))
18361854
|
18371855
n2.isBefore(getRankedCaseCfgOrder(switch, i + 1))
18381856
or
@@ -1846,15 +1864,15 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
18461864
(
18471865
if exists(case.getPattern(_))
18481866
then n2.isBefore(case.getPattern(0))
1849-
else n2.isAfterValue(case, any(MatchingSuccessor t | t.getValue() = true))
1867+
else explicitAfterValue(n2, case, any(MatchingSuccessor t | t.getValue() = true))
18501868
)
18511869
or
1852-
exists(int i, MatchingSuccessor ms | n1.isAfterValue(case.getPattern(i), ms) |
1870+
exists(int i, MatchingSuccessor ms | explicitAfterValue(n1, case.getPattern(i), ms) |
18531871
ms.getValue() = false and
18541872
n2.isBefore(case.getPattern(i + 1))
18551873
or
18561874
(ms.getValue() = true or not exists(case.getPattern(i + 1))) and
1857-
n2.isAfterValue(case, ms)
1875+
explicitAfterValue(n2, case, ms)
18581876
)
18591877
or
18601878
exists(PreControlFlowNode beforeGuard, PreControlFlowNode beforeBody |
@@ -1870,10 +1888,10 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
18701888
beforeBody.isAfter(any(Switch s | s.getCase(_) = case))
18711889
)
18721890
|
1873-
n1.isAfterValue(case, any(MatchingSuccessor t | t.getValue() = true)) and
1891+
explicitAfterValue(n1, case, any(MatchingSuccessor t | t.getValue() = true)) and
18741892
n2 = beforeGuard
18751893
or
1876-
n1.isAfterTrue(case.getGuard()) and
1894+
explicitAfterValue(n1, case.getGuard(), any(BooleanSuccessor b | b.getValue() = true)) and
18771895
n2 = beforeBody
18781896
)
18791897
)

0 commit comments

Comments
 (0)