Cleanup, printCFG

Co-authored-by: yoff <yoff@github.com>
This commit is contained in:
Taus
2026-04-28 14:59:11 +00:00
committed by yoff
parent a33b49a3f3
commit 68b3d57563
2 changed files with 86 additions and 2 deletions

View File

@@ -0,0 +1,45 @@
/**
* @name Print CFG (New)
* @description Produces a representation of a file's Control Flow Graph
* using the new shared control flow library.
* This query is used by the VS Code extension.
* @id python/print-cfg
* @kind graph
* @tags ide-contextual-queries/print-cfg
*/
private import python as Py
import semmle.python.controlflow.internal.AstNodeImpl
external string selectedSourceFile();
private predicate selectedSourceFileAlias = selectedSourceFile/0;
external int selectedSourceLine();
private predicate selectedSourceLineAlias = selectedSourceLine/0;
external int selectedSourceColumn();
private predicate selectedSourceColumnAlias = selectedSourceColumn/0;
module ViewCfgQueryInput implements ControlFlow::ViewCfgQueryInputSig<Py::File> {
predicate selectedSourceFile = selectedSourceFileAlias/0;
predicate selectedSourceLine = selectedSourceLineAlias/0;
predicate selectedSourceColumn = selectedSourceColumnAlias/0;
predicate cfgScopeSpan(
AstSigImpl::Callable callable, Py::File file, int startLine, int startColumn, int endLine,
int endColumn
) {
exists(Py::Scope scope |
scope = callable.asScope() and
file = scope.getLocation().getFile() and
scope.getLocation().hasLocationInfo(_, startLine, startColumn, endLine, endColumn)
)
}
}
import ControlFlow::ViewCfgQuery<Py::File, ViewCfgQueryInput>

View File

@@ -11,6 +11,7 @@
private import python as Py
private import codeql.controlflow.ControlFlowGraph
private import codeql.controlflow.SuccessorType
private import codeql.util.Void
private module Ast {
/** The newtype representing AST nodes for the shared CFG library. */
@@ -717,6 +718,8 @@ module AstSigImpl implements AstSig<Py::Location> {
index = 0 and result = w.getTest()
or
index = 1 and result = w.getBody()
or
index = 2 and result = w.getOrelse()
)
or
// ForStmt (mapped as ForeachStmt): collection (0), variable (1), body (2)
@@ -1046,12 +1049,17 @@ module AstSigImpl implements AstSig<Py::Location> {
Expr getExpr() { result = this.getValue() }
}
/** A `raise` statement (mapped to `ThrowStmt`). */
class ThrowStmt extends Stmt, Ast::RaiseNode {
/** A `raise` statement (mapped to `Throw`). */
class Throw extends Stmt, Ast::RaiseNode {
/** Gets the expression being raised. */
Expr getExpr() { result = this.getException() }
}
/** A `goto` statement. Python has no goto. */
class GotoStmt extends Stmt {
GotoStmt() { none() }
}
// ===== Try/except =====
/** A `try` statement. */
class TryStmt extends Stmt {
@@ -1171,6 +1179,26 @@ module AstSigImpl implements AstSig<Py::Location> {
NullCoalescingExpr() { none() }
}
/** An assignment expression. Python has no assignment expressions in the BinaryExpr sense. */
class Assignment extends BinaryExpr {
Assignment() { none() }
}
/** A simple assignment expression. */
class AssignExpr extends Assignment { }
/** A compound assignment expression. */
class CompoundAssignment extends Assignment { }
/** A short-circuiting logical AND compound assignment. Python has no `&&=` operator. */
class AssignLogicalAndExpr extends CompoundAssignment { }
/** A short-circuiting logical OR compound assignment. Python has no `||=` operator. */
class AssignLogicalOrExpr extends CompoundAssignment { }
/** A short-circuiting null-coalescing compound assignment. Python has no `??=` operator. */
class AssignNullCoalescingExpr extends CompoundAssignment { }
/** A unary expression. Exists for the `not` subclass. */
class UnaryExpr extends Expr {
UnaryExpr() { this instanceof Ast::NotExprNode }
@@ -1186,6 +1214,15 @@ module AstSigImpl implements AstSig<Py::Location> {
/** Gets the boolean value of this literal. */
boolean getValue() { result = this.getBoolValue() }
}
/** A pattern match expression. Python has no `instanceof`-style pattern match expr. */
class PatternMatchExpr extends Expr {
PatternMatchExpr() { none() }
Expr getExpr() { none() }
AstNode getPattern() { none() }
}
}
private module Cfg0 = Make0<Py::Location, AstSigImpl>;
@@ -1209,6 +1246,8 @@ private module Input implements InputSig1, InputSig2 {
string toString() { result = "label" }
}
class CallableBodyPartContext = Void;
predicate inConditionalContext(AstSigImpl::AstNode n, ConditionKind kind) {
kind.isBoolean() and
n = any(Ast::AssertNode a).getTest()