diff --git a/python/extractor/semmle/python/passes/pruner.py b/python/extractor/semmle/python/passes/pruner.py index fe3b03d453cd..5b69ec25bf3d 100644 --- a/python/extractor/semmle/python/passes/pruner.py +++ b/python/extractor/semmle/python/passes/pruner.py @@ -203,7 +203,8 @@ def __init__(self): self.nodes = set() def visit_MatchLiteralPattern(self, node): - # MatchLiteralPatterns _look_ like boolean tests, but are not. + # MatchLiteralPatterns _look_ like boolean tests in that they have both a true ("matched") + # and false ("didn't match") successor, but are not. # Thus, without this check, we would interpret # # match x: @@ -212,8 +213,7 @@ def visit_MatchLiteralPattern(self, node): # # (and similarly for True) as if it was a boolean test. This would cause the true edge # (leading to pass) to be pruned later on. - if isinstance(node.literal, ast.Name) and node.literal.id in ('True', 'False'): - self.nodes.add(node.literal) + self.nodes.add(node.literal) class NonlocalVisitor(ASTVisitor): def __init__(self): diff --git a/python/ql/lib/change-notes/2025-02-11-fix-match-literal-pruning.md b/python/ql/lib/change-notes/2025-02-11-fix-match-literal-pruning.md new file mode 100644 index 000000000000..957f2a4ca99c --- /dev/null +++ b/python/ql/lib/change-notes/2025-02-11-fix-match-literal-pruning.md @@ -0,0 +1,5 @@ +--- +category: fix +--- + +- `MatchLiteralPattern`s such as `case None: ...` are now never pruned from the extracted source code. This fixes some situations where code was wrongly identified as unreachable. diff --git a/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected b/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected index f5e74fab8d49..2417041f472d 100644 --- a/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected +++ b/python/ql/test/query-tests/Statements/unreachable/UnreachableCode.expected @@ -4,6 +4,3 @@ | test.py:21:5:21:38 | For | This statement is unreachable. | | test.py:28:9:28:21 | ExprStmt | This statement is unreachable. | | test.py:84:5:84:21 | ExceptStmt | This statement is unreachable. | -| test.py:158:9:159:16 | Case | This statement is unreachable. | -| test.py:162:13:162:16 | Pass | This statement is unreachable. | -| test.py:167:13:167:16 | Pass | This statement is unreachable. |