Skip to content

Commit

Permalink
Python: Fix pruning of literals in match pattern
Browse files Browse the repository at this point in the history
Co-authored-by: yoff <[email protected]>
  • Loading branch information
tausbn and yoff committed Nov 19, 2024
1 parent 95a8881 commit a4ccda5
Showing 1 changed file with 23 additions and 0 deletions.
23 changes: 23 additions & 0 deletions python/extractor/semmle/python/passes/pruner.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,25 @@ def visit_Attribute(self, node):
if isinstance(node.value, ast.Name):
self.nodes.add(node.value)

class NotBooleanTestVisitor(ASTVisitor):
"""Visitor that checks if a test is not a boolean test."""

def __init__(self):
self.nodes = set()

def visit_MatchLiteralPattern(self, node):
# MatchLiteralPatterns _look_ like boolean tests, but are not.
# Thus, without this check, we would interpret
#
# match x:
# case False:
# pass
#
# (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)

class NonlocalVisitor(ASTVisitor):
def __init__(self):
self.names = set()
Expand Down Expand Up @@ -306,6 +325,8 @@ def effective_constants_definitions(bool_const_defns, graph, branching_edges):
def do_pruning(tree, graph):
v = BoolConstVisitor()
v.visit(tree)
not_boolean_test = NotBooleanTestVisitor()
not_boolean_test.visit(tree)
nonlocals = NonlocalVisitor()
nonlocals.visit(tree)
global_vars = GlobalVisitor()
Expand Down Expand Up @@ -353,6 +374,8 @@ def do_pruning(tree, graph):
b = const_value(pred.node)
if b is None:
continue
if pred.node in not_boolean_test.nodes:
continue
if b.contradicts(val):
to_be_removed.add((pred, succ))
if not to_be_removed:
Expand Down

0 comments on commit a4ccda5

Please sign in to comment.