From 93112b2b75ca78986cb682221c76332931c2f740 Mon Sep 17 00:00:00 2001 From: Copilot Date: Tue, 5 May 2026 14:56:18 +0000 Subject: [PATCH] Python: include try-else in getChild for completion propagation The shared CFG library propagates abrupt completions from child to parent via getChild(parent, _) = child. Python's try.getElse() was wired into normal step rules but not listed in getChild(TryStmt, ...), so return/break/continue/raise statements occurring inside a try-else block had no parent path and ended up as dead-end CFG nodes. Add the else block at index -2 (alongside finally at -1). This affects only completion propagation; the normal-flow CFG is unchanged because TryStmt has explicit step rules. Verified on a CPython database: all 11 shared-CFG consistency queries now pass with 0 violations (deadEnd: 244 -> 0). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll b/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll index eb21cf32b1d..da960060edf 100644 --- a/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll +++ b/python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll @@ -969,13 +969,15 @@ module Ast implements AstSig { index = 1 and result = r.getCause() ) or - // TryStmt: body (0), handlers (1..n), finally (-1) + // TryStmt: body (0), handlers (1..n), else (-2), finally (-1) exists(TryStmt t | t = n | index = 0 and result = t.getBody() or result = t.getCatch(index - 1) and index >= 1 or index = -1 and result = t.getFinally() + or + index = -2 and result = t.getElse() ) or // Switch (match): subject (0), cases (1..n)