From 99e9d6ea2c1b049a306af0c2b7722cf563124d68 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 5 Dec 2025 13:23:11 +0000 Subject: [PATCH 1/4] Python: Add overlay annotations to AST classes ... and everything else that it depends on. --- python/ql/lib/semmle/python/AstExtended.qll | 3 +++ python/ql/lib/semmle/python/AstGenerated.qll | 2 ++ python/ql/lib/semmle/python/Class.qll | 2 ++ python/ql/lib/semmle/python/Comment.qll | 2 ++ python/ql/lib/semmle/python/Comprehensions.qll | 3 +++ python/ql/lib/semmle/python/Constants.qll | 2 ++ python/ql/lib/semmle/python/Exprs.qll | 3 +++ python/ql/lib/semmle/python/Files.qll | 3 +++ python/ql/lib/semmle/python/Flow.qll | 3 +++ python/ql/lib/semmle/python/Function.qll | 3 +++ python/ql/lib/semmle/python/GuardedControlFlow.qll | 3 +++ python/ql/lib/semmle/python/Import.qll | 3 +++ python/ql/lib/semmle/python/Keywords.qll | 3 +++ python/ql/lib/semmle/python/Module.qll | 3 +++ python/ql/lib/semmle/python/Operations.qll | 3 +++ python/ql/lib/semmle/python/Patterns.qll | 2 ++ python/ql/lib/semmle/python/SSA.qll | 2 ++ python/ql/lib/semmle/python/Scope.qll | 5 +++++ python/ql/lib/semmle/python/Stmts.qll | 3 +++ python/ql/lib/semmle/python/Variables.qll | 3 +++ python/ql/lib/semmle/python/essa/Definitions.qll | 3 +++ python/ql/lib/semmle/python/essa/Essa.qll | 2 ++ python/ql/lib/semmle/python/essa/SsaCompute.qll | 2 ++ python/ql/lib/semmle/python/essa/SsaDefinitions.qll | 2 ++ python/ql/lib/semmle/python/internal/CachedStages.qll | 1 + python/ql/lib/semmle/python/types/Builtins.qll | 3 +++ python/ql/lib/semmle/python/types/ImportTime.qll | 3 +++ 27 files changed, 72 insertions(+) diff --git a/python/ql/lib/semmle/python/AstExtended.qll b/python/ql/lib/semmle/python/AstExtended.qll index 73292b85c3a8..13da4e899a71 100644 --- a/python/ql/lib/semmle/python/AstExtended.qll +++ b/python/ql/lib/semmle/python/AstExtended.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python private import semmle.python.internal.CachedStages diff --git a/python/ql/lib/semmle/python/AstGenerated.qll b/python/ql/lib/semmle/python/AstGenerated.qll index 12f868323878..8805a43bec38 100644 --- a/python/ql/lib/semmle/python/AstGenerated.qll +++ b/python/ql/lib/semmle/python/AstGenerated.qll @@ -3,6 +3,8 @@ * WARNING: Any modifications to this file will be lost. * Relations can be changed by modifying master.py. */ +overlay[local] +module; import python diff --git a/python/ql/lib/semmle/python/Class.qll b/python/ql/lib/semmle/python/Class.qll index 19b81e86a125..cee0e730cb4f 100644 --- a/python/ql/lib/semmle/python/Class.qll +++ b/python/ql/lib/semmle/python/Class.qll @@ -1,6 +1,8 @@ /** * Provides classes representing Python classes. */ +overlay[local] +module; import python diff --git a/python/ql/lib/semmle/python/Comment.qll b/python/ql/lib/semmle/python/Comment.qll index 839d700b8cd1..c87ccc1521d2 100644 --- a/python/ql/lib/semmle/python/Comment.qll +++ b/python/ql/lib/semmle/python/Comment.qll @@ -1,6 +1,8 @@ /** * Provides classes representing comments in Python. */ +overlay[local] +module; import python diff --git a/python/ql/lib/semmle/python/Comprehensions.qll b/python/ql/lib/semmle/python/Comprehensions.qll index 37f07614282f..12e71e2d5d11 100644 --- a/python/ql/lib/semmle/python/Comprehensions.qll +++ b/python/ql/lib/semmle/python/Comprehensions.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /** The base class for list, set and dictionary comprehensions, and generator expressions. */ diff --git a/python/ql/lib/semmle/python/Constants.qll b/python/ql/lib/semmle/python/Constants.qll index 03254a4bfd04..f86019c0256f 100644 --- a/python/ql/lib/semmle/python/Constants.qll +++ b/python/ql/lib/semmle/python/Constants.qll @@ -1,4 +1,6 @@ /** Standard builtin types and modules */ +overlay[local] +module; import python diff --git a/python/ql/lib/semmle/python/Exprs.qll b/python/ql/lib/semmle/python/Exprs.qll index c374863d684e..6ab9f8d8340d 100644 --- a/python/ql/lib/semmle/python/Exprs.qll +++ b/python/ql/lib/semmle/python/Exprs.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import python private import semmle.python.internal.CachedStages diff --git a/python/ql/lib/semmle/python/Files.qll b/python/ql/lib/semmle/python/Files.qll index 2da0dd61f885..bb3c504654e7 100644 --- a/python/ql/lib/semmle/python/Files.qll +++ b/python/ql/lib/semmle/python/Files.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local] +module; import python private import codeql.util.FileSystem @@ -178,6 +180,7 @@ class Container extends Impl::Container { override Container getParentContainer() { result = super.getParentContainer() } + overlay[global] Container getChildContainer(string baseName) { result = this.getAChildContainer() and result.getBaseName() = baseName diff --git a/python/ql/lib/semmle/python/Flow.qll b/python/ql/lib/semmle/python/Flow.qll index 898cd566ab96..b29f9fd13839 100644 --- a/python/ql/lib/semmle/python/Flow.qll +++ b/python/ql/lib/semmle/python/Flow.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python private import semmle.python.internal.CachedStages private import codeql.controlflow.BasicBlock as BB diff --git a/python/ql/lib/semmle/python/Function.qll b/python/ql/lib/semmle/python/Function.qll index e15d28d3a12b..c133275b8b78 100644 --- a/python/ql/lib/semmle/python/Function.qll +++ b/python/ql/lib/semmle/python/Function.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /** diff --git a/python/ql/lib/semmle/python/GuardedControlFlow.qll b/python/ql/lib/semmle/python/GuardedControlFlow.qll index 73ea183850af..3169e4d0c1ad 100644 --- a/python/ql/lib/semmle/python/GuardedControlFlow.qll +++ b/python/ql/lib/semmle/python/GuardedControlFlow.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /** A basic block which terminates in a condition, splitting the subsequent control flow */ diff --git a/python/ql/lib/semmle/python/Import.qll b/python/ql/lib/semmle/python/Import.qll index c75ef9f0c918..e8a7facccad3 100644 --- a/python/ql/lib/semmle/python/Import.qll +++ b/python/ql/lib/semmle/python/Import.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python private import semmle.python.types.Builtins private import semmle.python.internal.CachedStages diff --git a/python/ql/lib/semmle/python/Keywords.qll b/python/ql/lib/semmle/python/Keywords.qll index b7ecca528bb9..da7b582ef16b 100644 --- a/python/ql/lib/semmle/python/Keywords.qll +++ b/python/ql/lib/semmle/python/Keywords.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python class KeyValuePair extends KeyValuePair_, DictDisplayItem { diff --git a/python/ql/lib/semmle/python/Module.qll b/python/ql/lib/semmle/python/Module.qll index f22f0d6fe39f..a30aab452c38 100644 --- a/python/ql/lib/semmle/python/Module.qll +++ b/python/ql/lib/semmle/python/Module.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python private import semmle.python.internal.CachedStages diff --git a/python/ql/lib/semmle/python/Operations.qll b/python/ql/lib/semmle/python/Operations.qll index e8f5e4799a54..c6318af63e25 100644 --- a/python/ql/lib/semmle/python/Operations.qll +++ b/python/ql/lib/semmle/python/Operations.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /** The base class for operators */ diff --git a/python/ql/lib/semmle/python/Patterns.qll b/python/ql/lib/semmle/python/Patterns.qll index 9b4760611d00..fb99a123584e 100644 --- a/python/ql/lib/semmle/python/Patterns.qll +++ b/python/ql/lib/semmle/python/Patterns.qll @@ -1,6 +1,8 @@ /** * Wrapping generated AST classes: `Pattern_` and subclasses. */ +overlay[local] +module; import python diff --git a/python/ql/lib/semmle/python/SSA.qll b/python/ql/lib/semmle/python/SSA.qll index b71bd95de795..777792877340 100644 --- a/python/ql/lib/semmle/python/SSA.qll +++ b/python/ql/lib/semmle/python/SSA.qll @@ -1,4 +1,6 @@ /** SSA library */ +overlay[local] +module; import python diff --git a/python/ql/lib/semmle/python/Scope.qll b/python/ql/lib/semmle/python/Scope.qll index 4131455299cb..66a7170aec77 100644 --- a/python/ql/lib/semmle/python/Scope.qll +++ b/python/ql/lib/semmle/python/Scope.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python private import semmle.python.dataflow.new.internal.ImportResolution @@ -6,6 +9,7 @@ private import semmle.python.dataflow.new.internal.ImportResolution * * This aims to be the same as m.getAnExport(), but without using the points-to machinery. */ +overlay[global] private string getAModuleExport(Module m) { py_exports(m, result) or @@ -76,6 +80,7 @@ class Scope extends Scope_ { predicate isTopLevel() { this.getEnclosingModule() = this.getEnclosingScope() } /** Holds if this scope is deemed to be public */ + overlay[global] predicate isPublic() { /* Not inside a function */ not this.getEnclosingScope() instanceof Function and diff --git a/python/ql/lib/semmle/python/Stmts.qll b/python/ql/lib/semmle/python/Stmts.qll index ea309227af67..c0dfac10ee84 100644 --- a/python/ql/lib/semmle/python/Stmts.qll +++ b/python/ql/lib/semmle/python/Stmts.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /** A statement */ diff --git a/python/ql/lib/semmle/python/Variables.qll b/python/ql/lib/semmle/python/Variables.qll index 1249fd020caa..d2baf04a5bf1 100644 --- a/python/ql/lib/semmle/python/Variables.qll +++ b/python/ql/lib/semmle/python/Variables.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /** A variable, either a global or local variable (including parameters) */ diff --git a/python/ql/lib/semmle/python/essa/Definitions.qll b/python/ql/lib/semmle/python/essa/Definitions.qll index aca6991b9f69..6e7b8d5b376a 100644 --- a/python/ql/lib/semmle/python/essa/Definitions.qll +++ b/python/ql/lib/semmle/python/essa/Definitions.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /* * Classification of variables. These should be non-overlapping and complete. diff --git a/python/ql/lib/semmle/python/essa/Essa.qll b/python/ql/lib/semmle/python/essa/Essa.qll index 384bfd2f91fe..ebc22beedf33 100644 --- a/python/ql/lib/semmle/python/essa/Essa.qll +++ b/python/ql/lib/semmle/python/essa/Essa.qll @@ -1,6 +1,8 @@ /** * Library for SSA representation (Static Single Assignment form). */ +overlay[local] +module; import python private import SsaCompute diff --git a/python/ql/lib/semmle/python/essa/SsaCompute.qll b/python/ql/lib/semmle/python/essa/SsaCompute.qll index d2512eecdede..fb030b6250ee 100644 --- a/python/ql/lib/semmle/python/essa/SsaCompute.qll +++ b/python/ql/lib/semmle/python/essa/SsaCompute.qll @@ -88,6 +88,8 @@ * ``` * and thus it falls out that `g3` must be `1`. */ +overlay[local] +module; import python private import semmle.python.internal.CachedStages diff --git a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll index 6c87af102fa9..827bee34474e 100644 --- a/python/ql/lib/semmle/python/essa/SsaDefinitions.qll +++ b/python/ql/lib/semmle/python/essa/SsaDefinitions.qll @@ -2,6 +2,8 @@ * Provides classes and predicates for determining the uses and definitions of * variables for ESSA form. */ +overlay[local] +module; import python private import semmle.python.internal.CachedStages diff --git a/python/ql/lib/semmle/python/internal/CachedStages.qll b/python/ql/lib/semmle/python/internal/CachedStages.qll index 687cabeceaed..df96e8498556 100644 --- a/python/ql/lib/semmle/python/internal/CachedStages.qll +++ b/python/ql/lib/semmle/python/internal/CachedStages.qll @@ -35,6 +35,7 @@ module Stages { * Computes predicates based on the AST. * These include SSA and basic-blocks. */ + overlay[local] cached module AST { /** diff --git a/python/ql/lib/semmle/python/types/Builtins.qll b/python/ql/lib/semmle/python/types/Builtins.qll index 796397f72cd6..371cf758d5c5 100644 --- a/python/ql/lib/semmle/python/types/Builtins.qll +++ b/python/ql/lib/semmle/python/types/Builtins.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import python private import LegacyPointsTo diff --git a/python/ql/lib/semmle/python/types/ImportTime.qll b/python/ql/lib/semmle/python/types/ImportTime.qll index 1604013d7ff4..27f70b09aa40 100644 --- a/python/ql/lib/semmle/python/types/ImportTime.qll +++ b/python/ql/lib/semmle/python/types/ImportTime.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import python /** From 41e88534609f7f3ceb8ab9203021c3cbb687f9db Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 5 Dec 2025 13:48:28 +0000 Subject: [PATCH 2/4] Python: Fix broken queries --- python/ql/lib/analysis/DefinitionTracking.qll | 7 +++---- .../LoopVariableCapture/LoopVariableCaptureQuery.qll | 8 +++++--- python/ql/src/analysis/ImportFailure.ql | 6 ++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/python/ql/lib/analysis/DefinitionTracking.qll b/python/ql/lib/analysis/DefinitionTracking.qll index 0d58bd69b7b6..21155970375b 100644 --- a/python/ql/lib/analysis/DefinitionTracking.qll +++ b/python/ql/lib/analysis/DefinitionTracking.qll @@ -471,11 +471,10 @@ Definition getUniqueDefinition(Expr use) { not result = TLocalDefinition(use) } -/** A helper class to get suitable locations for attributes */ -class NiceLocationExpr extends Expr { - /** Gets a textual representation of this element. */ - override string toString() { result = this.(Expr).toString() } +final class FinalExpr = Expr; +/** A helper class to get suitable locations for attributes */ +class NiceLocationExpr extends FinalExpr { /** * Holds if this element is at the specified location. * The location spans column `bc` of line `bl` to diff --git a/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll b/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll index 7f25701cac8e..987740236f24 100644 --- a/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll +++ b/python/ql/src/Variables/LoopVariableCapture/LoopVariableCaptureQuery.qll @@ -3,8 +3,10 @@ import python import semmle.python.dataflow.new.DataFlow +final class FinalAstNode = AstNode; + /** A looping construct. */ -abstract class Loop extends AstNode { +abstract class Loop extends FinalAstNode { /** * Gets a loop variable of this loop. * For example, `x` and `y` in `for x,y in pairs: print(x+y)` @@ -13,9 +15,9 @@ abstract class Loop extends AstNode { } /** A `for` loop. */ -private class ForLoop extends Loop, For { +private class ForLoop extends Loop instanceof For { override Variable getALoopVariable() { - this.getTarget() = result.getAnAccess().getParentNode*() and + this.(For).getTarget() = result.getAnAccess().getParentNode*() and result.getScope() = this.getScope() } } diff --git a/python/ql/src/analysis/ImportFailure.ql b/python/ql/src/analysis/ImportFailure.ql index c9289a8b474a..71967e6e04f7 100644 --- a/python/ql/src/analysis/ImportFailure.ql +++ b/python/ql/src/analysis/ImportFailure.ql @@ -59,7 +59,9 @@ predicate ok_to_fail(ImportExpr ie) { os_specific_import(ie) != get_os() } -class VersionTest extends ControlFlowNode { +final class FinalControlFlowNode = ControlFlowNode; + +class VersionTest extends FinalControlFlowNode { VersionTest() { exists(string name | name.matches("%version%") and @@ -70,7 +72,7 @@ class VersionTest extends ControlFlowNode { ) } - override string toString() { result = "VersionTest" } + string toString() { result = "VersionTest" } } /** A guard on the version of the Python interpreter */ From 846da9c030b6ae0e955268d46624b4dae11d9058 Mon Sep 17 00:00:00 2001 From: Taus Date: Wed, 17 Dec 2025 12:29:10 +0000 Subject: [PATCH 3/4] WIP --- python/ql/lib/semmle/python/ApiGraphs.qll | 2 ++ .../python/dataflow/new/FlowSummary.qll | 1 + .../python/dataflow/new/internal/Builtins.qll | 2 ++ .../new/internal/DataFlowDispatch.qll | 30 +++++++++++++++++++ .../dataflow/new/internal/DataFlowPrivate.qll | 6 ++++ .../dataflow/new/internal/DataFlowPublic.qll | 17 +++++------ .../dataflow/new/internal/FlowSummaryImpl.qll | 2 ++ .../dataflow/new/internal/ImportStar.qll | 3 ++ .../new/internal/IterableUnpacking.qll | 2 ++ .../dataflow/new/internal/LocalSources.qll | 2 ++ .../dataflow/new/internal/MatchUnpacking.qll | 2 ++ .../dataflow/new/internal/VariableCapture.qll | 2 ++ .../ql/lib/semmle/python/frameworks/Flask.qll | 2 ++ .../lib/semmle/python/frameworks/Stdlib.qll | 2 ++ .../python/frameworks/data/ModelsAsData.qll | 2 ++ .../data/internal/ApiGraphModelsSpecific.qll | 2 ++ .../semmle/python/internal/CachedStages.qll | 1 + .../dataflow/summaries/TestSummaries.qll | 3 ++ .../typetracking-summaries/TestSummaries.qll | 3 ++ 19 files changed, 77 insertions(+), 9 deletions(-) diff --git a/python/ql/lib/semmle/python/ApiGraphs.qll b/python/ql/lib/semmle/python/ApiGraphs.qll index b45c10e1417e..efd8141efc6e 100644 --- a/python/ql/lib/semmle/python/ApiGraphs.qll +++ b/python/ql/lib/semmle/python/ApiGraphs.qll @@ -451,6 +451,7 @@ module API { * allowing this predicate to be used in a negative * context when constructing new nodes. */ + overlay[local] predicate moduleImportExists(string m) { Impl::isImported(m) and // restrict `moduleImport` so it will never give results for a dotted name. Note @@ -695,6 +696,7 @@ module API { * * This is determined syntactically. */ + overlay[local] cached predicate isImported(string name) { // Ignore the following module name for Python 2, as we alias `__builtin__` to `builtins` elsewhere diff --git a/python/ql/lib/semmle/python/dataflow/new/FlowSummary.qll b/python/ql/lib/semmle/python/dataflow/new/FlowSummary.qll index 7a54ace60ed8..663b1be4e186 100644 --- a/python/ql/lib/semmle/python/dataflow/new/FlowSummary.qll +++ b/python/ql/lib/semmle/python/dataflow/new/FlowSummary.qll @@ -23,6 +23,7 @@ deprecated class SummaryComponentStack = Impl::Private::SummaryComponentStack; deprecated module SummaryComponentStack = Impl::Private::SummaryComponentStack; /** A callable with a flow summary, identified by a unique string. */ +overlay[local] abstract class SummarizedCallable extends LibraryCallable, Impl::Public::SummarizedCallable { bindingset[this] SummarizedCallable() { any() } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/Builtins.qll b/python/ql/lib/semmle/python/dataflow/new/internal/Builtins.qll index 9ed9e7d7a2b0..6a66d241083a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/Builtins.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/Builtins.qll @@ -1,4 +1,6 @@ /** Provides predicates for reasoning about built-ins in Python. */ +overlay[local] +module; private import python private import semmle.python.dataflow.new.DataFlow diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll index c717cd7bc97b..50b0917def08 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll @@ -31,6 +31,8 @@ * Note: This hasn't been 100% realized yet, so we don't currently expose a predicate to * ask what targets any data-flow node has. But it's still the plan to do this! */ +overlay[local?] +module; private import python private import DataFlowPublic @@ -39,6 +41,7 @@ private import FlowSummaryImpl as FlowSummaryImpl private import semmle.python.internal.CachedStages private import semmle.python.dataflow.new.internal.TypeTrackingImpl::CallGraphConstruction as CallGraphConstruction +overlay[local] newtype TParameterPosition = /** Used for `self` in methods, and `cls` in classmethods. */ TSelfParameterPosition() or @@ -84,6 +87,7 @@ newtype TParameterPosition = TSynthDictSplatParameterPosition() /** A parameter position. */ +overlay[local] class ParameterPosition extends TParameterPosition { /** Holds if this position represents a `self`/`cls` parameter. */ predicate isSelf() { this = TSelfParameterPosition() } @@ -146,6 +150,7 @@ class ParameterPosition extends TParameterPosition { } } +overlay[local] newtype TArgumentPosition = /** Used for `self` in methods, and `cls` in classmethods. */ TSelfArgumentPosition() or @@ -180,6 +185,7 @@ newtype TArgumentPosition = TDictSplatArgumentPosition() /** An argument position. */ +overlay[local] class ArgumentPosition extends TArgumentPosition { /** Holds if this position represents a `self`/`cls` argument. */ predicate isSelf() { this = TSelfArgumentPosition() } @@ -248,6 +254,7 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { * `@staticmethod` decorator or by convention * (like a `__new__` method on a class is a classmethod even without the decorator). */ +overlay[local] predicate isStaticmethod(Function func) { exists(NameNode id | id.getId() = "staticmethod" and id.isGlobal() | func.getADecorator() = id.getNode() @@ -259,6 +266,7 @@ predicate isStaticmethod(Function func) { * `@classmethod` decorator or by convention * (like a `__new__` method on a class is a classmethod even without the decorator). */ +overlay[local] predicate isClassmethod(Function func) { exists(NameNode id | id.getId() = "classmethod" and id.isGlobal() | func.getADecorator() = id.getNode() @@ -275,6 +283,7 @@ predicate isClassmethod(Function func) { } /** Holds if the function `func` has a `property` decorator. */ +overlay[local] predicate hasPropertyDecorator(Function func) { exists(NameNode id | id.getId() = "property" and id.isGlobal() | func.getADecorator() = id.getNode() @@ -284,6 +293,7 @@ predicate hasPropertyDecorator(Function func) { /** * Holds if the function `func` has a `contextlib.contextmanager`. */ +overlay[local] predicate hasContextmanagerDecorator(Function func) { exists(ControlFlowNode contextmanager | contextmanager.(NameNode).getId() = "contextmanager" and contextmanager.(NameNode).isGlobal() @@ -298,20 +308,25 @@ predicate hasContextmanagerDecorator(Function func) { // Callables // ============================================================================= /** A callable defined in library code, identified by a unique string. */ +overlay[local] abstract class LibraryCallable extends string { bindingset[this] LibraryCallable() { any() } /** Gets a call to this library callable. */ + overlay[global] abstract CallCfgNode getACall(); /** Same as `getACall` but without referring to the call graph or API graph. */ + overlay[global] CallCfgNode getACallSimple() { none() } /** Gets a data-flow node, where this library callable is used as a call-back. */ + overlay[global] abstract ArgumentNode getACallback(); } +overlay[local] newtype TDataFlowCallable = /** * Is used as the target for all calls: plain functions, lambdas, methods on classes, @@ -329,6 +344,7 @@ newtype TDataFlowCallable = TLibraryCallable(LibraryCallable callable) /** A callable. */ +overlay[local] abstract class DataFlowCallable extends TDataFlowCallable { /** Gets a textual representation of this element. */ abstract string toString(); @@ -350,6 +366,7 @@ abstract class DataFlowCallable extends TDataFlowCallable { } /** A callable function. */ +overlay[local] abstract class DataFlowFunction extends DataFlowCallable, TFunction { Function func; @@ -370,6 +387,7 @@ abstract class DataFlowFunction extends DataFlowCallable, TFunction { /** Gets the positional parameter offset, to take into account self/cls parameters. */ int positionalOffset() { result = 0 } + overlay[local] override ParameterNode getParameter(ParameterPosition ppos) { // Do not handle lower bound positions (such as `[1..]`) here // they are handled by parameter matching and would create @@ -408,11 +426,13 @@ abstract class DataFlowFunction extends DataFlowCallable, TFunction { } /** A plain (non-method) function. */ +overlay[local] class DataFlowPlainFunction extends DataFlowFunction { DataFlowPlainFunction() { not this instanceof DataFlowMethod } } /** A method. */ +overlay[local] class DataFlowMethod extends DataFlowFunction { Class cls; @@ -431,11 +451,13 @@ class DataFlowMethod extends DataFlowFunction { } /** A classmethod. */ +overlay[local] class DataFlowClassmethod extends DataFlowMethod { DataFlowClassmethod() { isClassmethod(func) } } /** A staticmethod. */ +overlay[local] class DataFlowStaticmethod extends DataFlowMethod, DataFlowFunction { DataFlowStaticmethod() { isStaticmethod(func) } @@ -450,6 +472,7 @@ class DataFlowStaticmethod extends DataFlowMethod, DataFlowFunction { * A module. This is not actually a callable, but we need this so a * `ModuleVariableNode` have an enclosing callable. */ +overlay[local] class DataFlowModuleScope extends DataFlowCallable, TModule { Module mod; @@ -466,6 +489,7 @@ class DataFlowModuleScope extends DataFlowCallable, TModule { override ParameterNode getParameter(ParameterPosition ppos) { none() } } +overlay[local] class LibraryCallableValue extends DataFlowCallable, TLibraryCallable { LibraryCallable callable; @@ -476,6 +500,7 @@ class LibraryCallableValue extends DataFlowCallable, TLibraryCallable { override string getQualifiedName() { result = callable.toString() } /** Gets a data-flow node, where this library callable is used as a call-back. */ + overlay[global] ArgumentNode getACallback() { result = callable.getACallback() } override Scope getScope() { none() } @@ -1589,6 +1614,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall { * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ +overlay[local] abstract class ParameterNodeImpl extends Node { /** Gets the `Parameter` this `ParameterNode` represents. */ abstract Parameter getParameter(); @@ -1610,6 +1636,7 @@ abstract class ParameterNodeImpl extends Node { * * This is used for tracking flow through captured variables. */ +overlay[local] class SynthCapturedVariablesParameterNode extends ParameterNodeImpl, TSynthCapturedVariablesParameterNode { @@ -1634,6 +1661,7 @@ class SynthCapturedVariablesParameterNode extends ParameterNodeImpl, } /** A parameter for a library callable with a flow summary. */ +overlay[local] class SummaryParameterNode extends ParameterNodeImpl, FlowSummaryNode { SummaryParameterNode() { FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _) @@ -1800,12 +1828,14 @@ DataFlowCallable viableCallable(DataFlowCall call) { // ============================================================================= // Remaining required data-flow things // ============================================================================= +overlay[local] private newtype TReturnKind = TNormalReturnKind() /** * A return kind. A return kind describes how a value can be returned * from a callable. For Python, this is simply a method return. */ +overlay[local] class ReturnKind extends TReturnKind { /** Gets a textual representation of this element. */ string toString() { result = "return" } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll index 2322539995b6..0cc4ffaed4b4 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import python private import DataFlowPublic private import semmle.python.essa.SsaCompute @@ -39,6 +42,7 @@ predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) //-------- // Nodes //-------- +overlay[local] predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr } // ============================================================================= @@ -111,6 +115,7 @@ class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode { * func = foo if else bar * func(1, 2, 3) */ +overlay[local] class SynthStarArgsElementParameterNode extends ParameterNodeImpl, TSynthStarArgsElementParameterNode { @@ -241,6 +246,7 @@ private predicate dictSplatParameterNodeClearStep(ParameterNode n, DictionaryEle * (c) since the synthesized nodes are hidden, the reported data-flow paths will be * collapsed anyway. */ +overlay[local] class SynthDictSplatParameterNode extends ParameterNodeImpl, TSynthDictSplatParameterNode { DataFlowCallable callable; diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll index ffecbcba57ac..4865c906991f 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -1,6 +1,8 @@ /** * Provides Python-specific definitions for use in the data flow library. */ +overlay[local] +module; private import python private import DataFlowPrivate @@ -22,6 +24,7 @@ private import semmle.python.frameworks.data.ModelsAsData * - Module variable nodes: These represent global variables and act as canonical targets for reads and writes of these. * - Synthetic nodes: These handle flow in various special cases. */ +overlay[local] newtype TNode = /** A node corresponding to a control flow node. */ TCfgNode(ControlFlowNode node) { @@ -76,15 +79,7 @@ newtype TNode = node.getNode() = any(Comp c).getIterable() } or /** A node representing a global (module-level) variable in a specific module. */ - TModuleVariableNode(Module m, GlobalVariable v) { - v.getScope() = m and - ( - v.escapes() - or - isAccessedThroughImportStar(m) and - ImportStar::globalNameDefinedInModule(v.getId(), m) - ) - } or + TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m } or /** * A synthetic node representing that an iterable sequence flows to consumer. */ @@ -151,6 +146,7 @@ private import semmle.python.internal.CachedStages * An element, viewed as a node in a data flow graph. Either an SSA variable * (`EssaNode`) or a control flow node (`CfgNode`). */ +overlay[local] class Node extends TNode { /** Gets a textual representation of this element. */ cached @@ -318,6 +314,7 @@ class ScopeEntryDefinitionNode extends Node, TScopeEntryDefinitionNode { * The value of a parameter at function entry, viewed as a node in a data * flow graph. */ +overlay[local] class ParameterNode extends Node instanceof ParameterNodeImpl { /** Gets the parameter corresponding to this node, if any. */ final Parameter getParameter() { result = super.getParameter() } @@ -613,6 +610,7 @@ module BarrierGuard { * Algebraic datatype for tracking data content associated with values. * Content can be collection elements or object attributes. */ +overlay[local] newtype TContent = /** An element of a list. */ TListElementContent() or @@ -684,6 +682,7 @@ newtype TContent = * If the value is a collection, it can have elements, * if it is an object, it can have attribute values. */ +overlay[local] class Content extends TContent { /** Gets a textual representation of this element. */ string toString() { result = "Content" } diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll index 396154c06ee8..886d6b97a4bb 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for defining flow summaries. */ +overlay[local] +module; private import python private import codeql.dataflow.internal.FlowSummaryImpl diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll b/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll index 564630c47dbc..740b075e52de 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll @@ -1,4 +1,6 @@ /** Provides predicates for reasoning about uses of `import *` in Python. */ +overlay[local] +module; private import python private import semmle.python.dataflow.new.internal.Builtins @@ -92,6 +94,7 @@ module ImportStar { * * this would return the data-flow nodes corresponding to `foo.bar` and `quux`. */ + overlay[local] cached ControlFlowNode potentialImportStarBase(Scope s) { result = any(ImportStarNode n | n.getScope() = s).getModule() diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/IterableUnpacking.qll b/python/ql/lib/semmle/python/dataflow/new/internal/IterableUnpacking.qll index e83e789c2fbc..5def15fa3c8a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/IterableUnpacking.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/IterableUnpacking.qll @@ -166,6 +166,8 @@ * * `c`: [ListElementContent] */ +overlay[local] +module; private import python private import DataFlowPublic diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll b/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll index c43a111c9c8b..e082a764d8c0 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll @@ -5,6 +5,8 @@ * Note that unlike `TypeTracker.qll`, this library only performs * local tracking within a function. */ +overlay[local] +module; private import python import DataFlowPublic diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/MatchUnpacking.qll b/python/ql/lib/semmle/python/dataflow/new/internal/MatchUnpacking.qll index 8064c34d9218..e72e378da528 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/MatchUnpacking.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/MatchUnpacking.qll @@ -50,6 +50,8 @@ * keyword arguments using the `__match_args__` attribute on the class. We do not * currently model this. */ +overlay[local] +module; private import python private import DataFlowPublic diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/VariableCapture.qll b/python/ql/lib/semmle/python/dataflow/new/internal/VariableCapture.qll index a7b3b9ceaebf..22e5cf8e4c30 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/VariableCapture.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/VariableCapture.qll @@ -1,4 +1,6 @@ /** Provides logic related to captured variables. */ +overlay[local] +module; private import python private import DataFlowPublic diff --git a/python/ql/lib/semmle/python/frameworks/Flask.qll b/python/ql/lib/semmle/python/frameworks/Flask.qll index 0e5d6065c474..442bced2fbb8 100644 --- a/python/ql/lib/semmle/python/frameworks/Flask.qll +++ b/python/ql/lib/semmle/python/frameworks/Flask.qll @@ -2,6 +2,8 @@ * Provides classes modeling security-relevant aspects of the `flask` PyPI package. * See https://flask.palletsprojects.com/en/1.1.x/. */ +overlay[local?] +module; private import python private import semmle.python.dataflow.new.DataFlow diff --git a/python/ql/lib/semmle/python/frameworks/Stdlib.qll b/python/ql/lib/semmle/python/frameworks/Stdlib.qll index 143a575c6e9c..0586018c4a37 100644 --- a/python/ql/lib/semmle/python/frameworks/Stdlib.qll +++ b/python/ql/lib/semmle/python/frameworks/Stdlib.qll @@ -2,6 +2,8 @@ * Provides classes modeling security-relevant aspects of the standard libraries. * Note: some modeling is done internally in the dataflow/taint tracking implementation. */ +overlay[local?] +module; private import python private import semmle.python.dataflow.new.DataFlow diff --git a/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll b/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll index 11c6b285f2aa..0d70f1f8e316 100644 --- a/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll +++ b/python/ql/lib/semmle/python/frameworks/data/ModelsAsData.qll @@ -8,6 +8,8 @@ * The package name refers to the top-level module the import comes from, and not a PyPI package. * So for `from foo.bar import baz`, the package will be `foo`. */ +overlay[local?] +module; private import python private import internal.ApiGraphModels as Shared diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll index 1b22e8740bc9..0da7f79070f1 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -30,6 +30,7 @@ import semmle.python.dataflow.new.DataFlow::DataFlow as DataFlow * Holds if models describing `type` may be relevant for the analysis of this database. */ bindingset[type] +overlay[local] predicate isTypeUsed(string type) { // If `type` is a path, then it is the first component that should be imported. API::moduleImportExists(type.splitAt(".", 0)) @@ -39,6 +40,7 @@ predicate isTypeUsed(string type) { * Holds if `type` can be obtained from an instance of `otherType` due to * language semantics modeled by `getExtraNodeFromType`. */ +overlay[local] predicate hasImplicitTypeModel(string type, string otherType) { none() } /** Gets a Python-specific interpretation of the `(type, path)` tuple after resolving the first `n` access path tokens. */ diff --git a/python/ql/lib/semmle/python/internal/CachedStages.qll b/python/ql/lib/semmle/python/internal/CachedStages.qll index df96e8498556..7379cc51372f 100644 --- a/python/ql/lib/semmle/python/internal/CachedStages.qll +++ b/python/ql/lib/semmle/python/internal/CachedStages.qll @@ -177,6 +177,7 @@ module Stages { * Always holds. * Ensures that a predicate is evaluated as part of the DataFlow stage. */ + overlay[local] cached predicate ref() { 1 = 1 } diff --git a/python/ql/test/library-tests/dataflow/summaries/TestSummaries.qll b/python/ql/test/library-tests/dataflow/summaries/TestSummaries.qll index 534fac624914..9037d2ec9415 100644 --- a/python/ql/test/library-tests/dataflow/summaries/TestSummaries.qll +++ b/python/ql/test/library-tests/dataflow/summaries/TestSummaries.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import python private import semmle.python.dataflow.new.FlowSummary private import semmle.python.ApiGraphs diff --git a/python/ql/test/library-tests/dataflow/typetracking-summaries/TestSummaries.qll b/python/ql/test/library-tests/dataflow/typetracking-summaries/TestSummaries.qll index 47e0fda7c0bb..efebc0016f69 100644 --- a/python/ql/test/library-tests/dataflow/typetracking-summaries/TestSummaries.qll +++ b/python/ql/test/library-tests/dataflow/typetracking-summaries/TestSummaries.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import python private import semmle.python.dataflow.new.FlowSummary private import semmle.python.ApiGraphs From 97e2376ada27231cca7964fa680d334c01b88e57 Mon Sep 17 00:00:00 2001 From: Taus Date: Wed, 7 Jan 2026 13:19:49 +0000 Subject: [PATCH 4/4] Fix remaining overlay[local] issues --- .../dataflow/new/internal/Attributes.qll | 2 ++ .../new/internal/DataFlowDispatch.qll | 26 ++++++++++++------- .../dataflow/new/internal/DataFlowPublic.qll | 12 ++++++--- .../dataflow/new/internal/FlowSummaryImpl.qll | 1 + .../dataflow/new/internal/ImportStar.qll | 3 +++ .../dataflow/new/internal/LocalSources.qll | 9 +++++-- .../ql/lib/semmle/python/internal/Awaited.qll | 2 ++ 7 files changed, 39 insertions(+), 16 deletions(-) diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll b/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll index e9bcc5e67855..8778ae288667 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/Attributes.qll @@ -1,4 +1,6 @@ /** This module provides an API for attribute reads and writes. */ +overlay[local] +module; private import python import DataFlowUtil diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll index 50b0917def08..e8379e303ace 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowDispatch.qll @@ -1235,6 +1235,7 @@ predicate resolveCall(CallNode call, Function target, CallType type) { * Holds if the argument of `call` at position `apos` is `arg`. This is just a helper * predicate that maps ArgumentPositions to the arguments of the underlying `CallNode`. */ +overlay[local] cached predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) { exists(int index | @@ -1712,6 +1713,7 @@ private class SummaryReturnNode extends FlowSummaryNode, ReturnNode { override ReturnKind getKind() { result = rk } } +overlay[global] private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode { private SummaryCall call_; private ArgumentPosition pos_; @@ -1750,18 +1752,18 @@ private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNodeImpl * `CallGraphConstruction::Make` in stead of * `CallGraphConstruction::Simple::Make` appropriately. */ -class CapturedVariablesArgumentNode extends CfgNode, ArgumentNode { +class CapturedVariablesArgumentNode extends CfgNode { CallNode callNode; - CapturedVariablesArgumentNode() { - node = callNode.getFunction() and - exists(Function target | resolveCall(callNode, target, _) | - target = any(VariableCapture::CapturedVariable v).getACapturingScope() - ) - } + CapturedVariablesArgumentNode() { node = callNode.getFunction() } override string toString() { result = "Capturing closure argument" } +} +class CapturedVariablesArgumentNodeAsArgumentNode extends CapturedVariablesArgumentNode, + ArgumentNode +{ + overlay[global] override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { callNode = call.getNode() and pos.isLambdaSelf() @@ -1769,9 +1771,8 @@ class CapturedVariablesArgumentNode extends CfgNode, ArgumentNode { } /** A synthetic node representing the values of variables captured by a comprehension. */ -class SynthCompCapturedVariablesArgumentNode extends Node, TSynthCompCapturedVariablesArgumentNode, - ArgumentNode -{ +overlay[local] +class SynthCompCapturedVariablesArgumentNode extends Node, TSynthCompCapturedVariablesArgumentNode { Comp comp; SynthCompCapturedVariablesArgumentNode() { this = TSynthCompCapturedVariablesArgumentNode(comp) } @@ -1783,7 +1784,12 @@ class SynthCompCapturedVariablesArgumentNode extends Node, TSynthCompCapturedVar override Location getLocation() { result = comp.getLocation() } Comp getComprehension() { result = comp } +} +class SynthCompCapturedVariablesArgumentNodeAsArgumentNode extends SynthCompCapturedVariablesArgumentNode, + ArgumentNode +{ + overlay[global] override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { call.(ComprehensionCall).getComprehension() = comp and pos.isLambdaSelf() diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll index 4865c906991f..85b990bc1ad2 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPublic.qll @@ -336,6 +336,7 @@ class LocalSourceParameterNode extends ExtractedParameterNode, LocalSourceNode { ExtractedParameterNode parameterNode(Parameter p) { result.getParameter() = p } /** A data flow node that represents a call argument. */ +overlay[global] abstract class ArgumentNode extends Node { /** Holds if this argument occurs at the given position in the given call. */ abstract predicate argumentOf(DataFlowCall call, ArgumentPosition pos); @@ -347,11 +348,12 @@ abstract class ArgumentNode extends Node { /** * A data flow node that represents a call argument found in the source code. */ +overlay[global] class ExtractedArgumentNode extends ArgumentNode { ExtractedArgumentNode() { // for resolved calls, we need to allow all argument nodes - getCallArg(_, _, _, this, _) - or + // getCallArg(_, _, _, this, _) + // or // for potential summaries we allow all normal call arguments normalCallArg(_, this, _) or @@ -436,6 +438,7 @@ class ModuleVariableNode extends Node, TModuleVariableNode { GlobalVariable getVariable() { result = var } /** Gets a node that reads this variable. */ + overlay[global] Node getARead() { result.asCfgNode() = var.getALoad().getAFlowNode() and // Ignore reads that happen when the module is imported. These are only executed once. @@ -463,12 +466,12 @@ class ModuleVariableNode extends Node, TModuleVariableNode { override Location getLocation() { result = mod.getLocation() } } -private predicate isAccessedThroughImportStar(Module m) { m = ImportStar::getStarImported(_) } - +overlay[global] private ModuleVariableNode import_star_read(Node n) { resolved_import_star_module(result.getModule(), result.getVariable().getId(), n) } +overlay[global] pragma[nomagic] private predicate resolved_import_star_module(Module m, string name, Node n) { exists(NameNode nn | nn = n.asCfgNode() | @@ -594,6 +597,7 @@ signature predicate guardChecksSig(GuardNode g, ControlFlowNode node, boolean br * This is expected to be used in `isBarrier`/`isSanitizer` definitions * in data flow and taint tracking. */ +overlay[global] module BarrierGuard { /** Gets a node that is safely guarded by the given guard check. */ ExprNode getABarrierNode() { diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll index 886d6b97a4bb..f690b2b5e4fc 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/FlowSummaryImpl.qll @@ -99,6 +99,7 @@ module Input implements InputSig private import Make as Impl private module StepsInput implements Impl::Private::StepsInputSig { + overlay[global] DataFlowCall getACall(Public::SummarizedCallable sc) { result = TPotentialLibraryCall([ diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll b/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll index 740b075e52de..83f8ee862c39 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/ImportStar.qll @@ -13,6 +13,7 @@ module ImportStar { * Holds if `n` is an access of a variable called `name` (which is _not_ the name of a * built-in, and which is _not_ a global defined in the enclosing module) inside the scope `s`. */ + overlay[local] cached predicate namePossiblyDefinedInImportStar(NameNode n, string name, Scope s) { n.isLoad() and @@ -63,6 +64,7 @@ module ImportStar { * Holds if `n` may refer to a global variable of the same name in the module `m`, accessible * from the scope of `n` by a chain of `import *` imports. */ + overlay[global] cached predicate importStarResolvesTo(NameNode n, Module m) { m = getStarImported+(n.getEnclosingModule()) and @@ -73,6 +75,7 @@ module ImportStar { /** * Gets a module that is imported from `m` via `import *`. */ + overlay[global] cached Module getStarImported(Module m) { exists(ImportStar i, DataFlow::CfgNode imported_module | diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll b/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll index e082a764d8c0..e33680a4a232 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/LocalSources.qll @@ -69,7 +69,7 @@ class LocalSourceNode extends Node { or // We explicitly include any read of a global variable, as some of these may have local flow going // into them. - this = any(ModuleVariableNode mvn).getARead() + this.asCfgNode() = any(GlobalVariable v).getALoad().getAFlowNode() or // We include all scope entry definitions, as these act as the local source within the scope they // enter. @@ -79,6 +79,7 @@ class LocalSourceNode extends Node { } /** Holds if this `LocalSourceNode` can flow to `nodeTo` in one or more local flow steps. */ + overlay[caller] pragma[inline] predicate flowsTo(Node nodeTo) { Cached::hasLocalSource(nodeTo, this) } @@ -151,6 +152,7 @@ class LocalSourceNode extends Node { * * See `TypeTracker` for more details about how to use this. */ + overlay[global] pragma[inline] LocalSourceNode track(TypeTracker t2, TypeTracker t) { t = t2.step(this, result) } @@ -159,6 +161,7 @@ class LocalSourceNode extends Node { * * See `TypeBackTracker` for more details about how to use this. */ + overlay[global] pragma[inline] LocalSourceNode backtrack(TypeBackTracker t2, TypeBackTracker t) { t = t2.step(result, this) } } @@ -212,6 +215,7 @@ private module FutureWork { * * See `TypeTracker` for more details about how to use this. */ + overlay[global] pragma[inline] TypeTrackingNode track(TypeTracker t2, TypeTracker t) { t = t2.step(this, result) } @@ -220,6 +224,7 @@ private module FutureWork { * * See `TypeBackTracker` for more details about how to use this. */ + overlay[global] pragma[inline] TypeTrackingNode backtrack(TypeBackTracker t2, TypeBackTracker t) { t2 = t.step(result, this) } } @@ -250,7 +255,7 @@ private module Cached { pragma[nomagic] private predicate localSourceFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo, _) and - not nodeTo = any(ModuleVariableNode v).getARead() + not nodeTo instanceof LocalSourceNode } /** diff --git a/python/ql/lib/semmle/python/internal/Awaited.qll b/python/ql/lib/semmle/python/internal/Awaited.qll index cd5162e6151e..43affdf95a4f 100644 --- a/python/ql/lib/semmle/python/internal/Awaited.qll +++ b/python/ql/lib/semmle/python/internal/Awaited.qll @@ -3,6 +3,8 @@ * * Provides helper class for defining additional API graph edges. */ +overlay[local] +module; private import python private import semmle.python.dataflow.new.DataFlow