mirror of
https://github.com/github/codeql.git
synced 2026-06-30 00:55:29 +02:00
Preparatory refactor for the shared-CFG dataflow migration. Adds the new Python SSA adapter additively, without changing any production behaviour. Library additions: - semmle.python.dataflow.new.internal.SsaImpl — Python SSA implementation built on the new (shared) CFG. Mirrors the Java SSA adapter (java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll): an InputSig is defined in terms of positional (BasicBlock, int) variable references, and the shared codeql.ssa.Ssa::Make<Location, Cfg, Input> module is then instantiated. SourceVariable is the AST-level Py::Variable. Variable references are looked up via the new CFG facade's NameNode.defines/uses/deletes predicates (added in the preceding PR), which themselves are one-line bridges to AST-level Name.defines/uses/deletes. Implicit-entry definitions are inserted for non-local/global/builtin reads, captured variables, and (when needed) parameters. Test additions: - library-tests/dataflow-new-ssa/ — exercises the new SSA over a representative test corpus and checks expected def/use chains. - library-tests/dataflow-new-ssa-vs-legacy/ — runs both new SSA and legacy ESSA over the same corpus and diffs the results, so any semantic divergence shows up as a test failure. Production impact: None. The new SSA adapter has zero callers in lib/ and src/ — the legacy ESSA SSA (semmle/python/essa/*) remains the default. The dataflow library is not migrated yet; that lands in a follow-up PR. Verified by: - All 367 lib + src + consistency-queries compile clean. - All 641 ControlFlow + PointsTo + dataflow + essa + consistency library-tests pass. - Both new dataflow-new-ssa[/vs-legacy] test packs pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
49 lines
1.4 KiB
Python
49 lines
1.4 KiB
Python
# Basic SSA tests for the new-CFG SSA adapter.
|
|
#
|
|
# The shared SSA implementation prunes its construction by liveness:
|
|
# definitions of variables that are not read are never materialised.
|
|
# This is by design — write-only variables would only bloat the SSA
|
|
# graph. Tests therefore must always include a read of each variable
|
|
# being verified.
|
|
#
|
|
# Annotations:
|
|
# def=<var>: there is an SSA write definition of <var> at this line
|
|
# use=<var>: <var> is used here and the read resolves to some def
|
|
#
|
|
# Note: a module-level `def name(...)` statement is itself a write
|
|
# definition of the module global `name`, which is live (it can be read
|
|
# externally), so every function below carries a `def=<name>` annotation
|
|
# on its `def` line.
|
|
|
|
|
|
def basic_param(x): # $ def=basic_param def=x
|
|
return x # $ use=x
|
|
|
|
|
|
def basic_assign(): # $ def=basic_assign
|
|
y = 1 # $ def=y
|
|
return y # $ use=y
|
|
|
|
|
|
def reassignment(): # $ def=reassignment
|
|
x = 1
|
|
x = 2 # $ def=x
|
|
return x # $ use=x
|
|
|
|
|
|
def if_else_phi(cond): # $ def=if_else_phi def=cond
|
|
if cond: # $ use=cond phi=x
|
|
x = 1 # $ def=x
|
|
else:
|
|
x = 2 # $ def=x
|
|
return x # $ use=x
|
|
|
|
|
|
# `some_undefined` is never assigned anywhere, so (matching legacy ESSA)
|
|
# the SSA library creates no entry definition for it: an undefined-name
|
|
# read resolves to no SSA def, hence there is no `use=` here.
|
|
def use_global(): # $ def=use_global
|
|
return some_undefined
|
|
|
|
|