Skip to content

Commit 53cae68

Browse files
authored
Merge pull request #21931 from github/yoff/python-shared-cfg-loop-else
Shared CFG: add defaulted getWhileElse/getForeachElse to AstSig
2 parents cfbf4a3 + 73ab3e6 commit 53cae68

1 file changed

Lines changed: 27 additions & 3 deletions

File tree

shared/controlflow/codeql/controlflow/ControlFlowGraph.qll

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ signature module AstSig<LocationSig Location> {
224224
*/
225225
default AstNode getTryElse(TryStmt try) { none() }
226226

227+
/**
228+
* Gets the `else` block of loop statement `loop`, if any.
229+
*
230+
* Only some languages (e.g. Python) support `for-else` constructs.
231+
*/
232+
default AstNode getLoopElse(LoopStmt loop) { none() }
233+
227234
/** A catch clause in a try statement. */
228235
class CatchClause extends AstNode {
229236
/** Gets the variable declared by this catch clause. */
@@ -1578,19 +1585,32 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
15781585
n2.isBefore(loopstmt.getBody())
15791586
or
15801587
n1.isAfterValue(cond, any(BooleanSuccessor b | b.getValue() = while.booleanNot())) and
1581-
n2.isAfter(loopstmt)
1588+
(
1589+
n2.isBefore(getLoopElse(loopstmt))
1590+
or
1591+
not exists(getLoopElse(loopstmt)) and n2.isAfter(loopstmt)
1592+
)
15821593
or
15831594
n1.isAfter(loopstmt.getBody()) and
15841595
n2.isAdditional(loopstmt, loopHeaderTag())
15851596
)
15861597
or
1598+
exists(LoopStmt loopstmt |
1599+
n1.isAfter(getLoopElse(loopstmt)) and
1600+
n2.isAfter(loopstmt)
1601+
)
1602+
or
15871603
exists(ForeachStmt foreachstmt |
15881604
n1.isBefore(foreachstmt) and
15891605
n2.isBefore(foreachstmt.getCollection())
15901606
or
15911607
n1.isAfterValue(foreachstmt.getCollection(),
15921608
any(EmptinessSuccessor t | t.getValue() = true)) and
1593-
n2.isAfter(foreachstmt)
1609+
(
1610+
n2.isBefore(getLoopElse(foreachstmt))
1611+
or
1612+
not exists(getLoopElse(foreachstmt)) and n2.isAfter(foreachstmt)
1613+
)
15941614
or
15951615
n1.isAfterValue(foreachstmt.getCollection(),
15961616
any(EmptinessSuccessor t | t.getValue() = false)) and
@@ -1603,7 +1623,11 @@ module Make0<LocationSig Location, AstSig<Location> Ast> {
16031623
n2.isAdditional(foreachstmt, loopHeaderTag())
16041624
or
16051625
n1.isAdditional(foreachstmt, loopHeaderTag()) and
1606-
n2.isAfter(foreachstmt)
1626+
(
1627+
n2.isBefore(getLoopElse(foreachstmt))
1628+
or
1629+
not exists(getLoopElse(foreachstmt)) and n2.isAfter(foreachstmt)
1630+
)
16071631
or
16081632
n1.isAdditional(foreachstmt, loopHeaderTag()) and
16091633
n2.isBefore(foreachstmt.getVariable())

0 commit comments

Comments
 (0)