From 84b03b2b1a5f65ce739e443afec5cbb696749572 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 31 Mar 2026 09:16:17 +0000 Subject: [PATCH] Add File as a CFG root to support file-level declarations Agent-Logs-Url: https://github.com/github/codeql/sessions/2867f173-c3f1-4564-9885-3ff4517bbf30 Co-authored-by: owen-mc <62447351+owen-mc@users.noreply.github.com> --- .../go/controlflow/ControlFlowGraph.qll | 21 +++++++++++++------ .../go/controlflow/ControlFlowGraphShared.qll | 11 +++++++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll index 49d11e3c561..0bbb3045d2d 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll @@ -9,17 +9,26 @@ private import ControlFlowGraphShared /** Provides helper predicates for mapping between CFG nodes and the AST. */ module ControlFlow { - /** A function with which a CFG is associated. */ + /** A file or function with which a CFG is associated. */ class Root extends AstNode { - Root() { exists(this.(FuncDef).getBody()) } + Root() { + exists(this.(FuncDef).getBody()) + or + exists(this.(File).getADecl()) + } - /** Holds if `nd` belongs to this function. */ - predicate isRootOf(AstNode nd) { this = nd.getEnclosingFunction() } + /** Holds if `nd` belongs to this file or function. */ + predicate isRootOf(AstNode nd) { + this = nd.getEnclosingFunction() + or + not exists(nd.getEnclosingFunction()) and + this = nd.getFile() + } - /** Gets the synthetic entry node of the CFG for this function. */ + /** Gets the synthetic entry node of the CFG for this file or function. */ EntryNode getEntryNode() { result = ControlFlow::entryNode(this) } - /** Gets the synthetic exit node of the CFG for this function. */ + /** Gets the synthetic exit node of the CFG for this file or function. */ ExitNode getExitNode() { result = ControlFlow::exitNode(this) } } diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll index c92ede1e9b9..00f366ea38c 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphShared.qll @@ -63,7 +63,11 @@ module GoCfg { } class Callable extends AstNode { - Callable() { exists(this.(Go::FuncDef).getBody()) } + Callable() { + exists(this.(Go::FuncDef).getBody()) + or + exists(this.(Go::File).getADecl()) + } } AstNode callableGetBody(Callable c) { result = c } @@ -72,6 +76,11 @@ module GoCfg { result = node and node instanceof Callable or not node instanceof Callable and result = node.getEnclosingFunction() + or + not node instanceof Callable and + not exists(node.getEnclosingFunction()) and + result = node.getFile() and + result instanceof Callable } class Stmt = Go::Stmt;