diff --git a/ql/ql/src/codeql/Locations.qll b/ql/ql/src/codeql/Locations.qll index ae8058c916df..e03c84f98fa5 100644 --- a/ql/ql/src/codeql/Locations.qll +++ b/ql/ql/src/codeql/Locations.qll @@ -1,4 +1,6 @@ /** Provides classes for working with locations. */ +overlay[local] +module; import files.FileSystem diff --git a/ql/ql/src/codeql/files/FileSystem.qll b/ql/ql/src/codeql/files/FileSystem.qll index 5a219f3b7f0c..52174250af0c 100644 --- a/ql/ql/src/codeql/files/FileSystem.qll +++ b/ql/ql/src/codeql/files/FileSystem.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local?] +module; private import codeql_ql.ast.internal.TreeSitter private import codeql.Locations diff --git a/ql/ql/src/codeql_ql/StructuredLogs.qll b/ql/ql/src/codeql_ql/StructuredLogs.qll index 4c0ef69fd554..87527eae1d23 100644 --- a/ql/ql/src/codeql_ql/StructuredLogs.qll +++ b/ql/ql/src/codeql_ql/StructuredLogs.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import ql private import codeql_ql.ast.internal.TreeSitter private import experimental.RA @@ -23,6 +26,7 @@ private float stringToTimestamp(string str) { } bindingset[s] +overlay[global] private Predicate getPredicateFromPosition(string s) { exists(string r, string filepath, int startline | r = "(.*):(\\d+),(\\d+)-(\\d+),(\\d+)" | filepath = s.regexpCapture(r, 1) and @@ -397,6 +401,7 @@ module KindPredicatesLog { string getPosition() { result = this.getString("position") } + overlay[global] Predicate getPredicate() { result = getPredicateFromPosition(this.getPosition()) } /** diff --git a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll index 2d4a9d654652..c81830e1d59a 100644 --- a/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll +++ b/ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll @@ -23,6 +23,7 @@ private predicate discardLocation(@location_default loc) { ) } +overlay[local] module QL { /** The base class for all AST nodes */ class AstNode extends @ql_ast_node { @@ -67,7 +68,6 @@ module QL { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@ql_ast_node node) { exists(@location_default loc | ql_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -75,7 +75,6 @@ module QL { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @ql_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1315,6 +1314,7 @@ module QL { } } +overlay[local] module Dbscheme { /** The base class for all AST nodes */ class AstNode extends @dbscheme_ast_node { @@ -1359,7 +1359,6 @@ module Dbscheme { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@dbscheme_ast_node node) { exists(@location_default loc | dbscheme_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -1367,7 +1366,6 @@ module Dbscheme { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @dbscheme_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1673,6 +1671,7 @@ module Dbscheme { } } +overlay[local] module Blame { /** The base class for all AST nodes */ class AstNode extends @blame_ast_node { @@ -1717,7 +1716,6 @@ module Blame { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@blame_ast_node node) { exists(@location_default loc | blame_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -1725,7 +1723,6 @@ module Blame { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @blame_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1808,6 +1805,7 @@ module Blame { } } +overlay[local] module JSON { /** The base class for all AST nodes */ class AstNode extends @json_ast_node { @@ -1852,7 +1850,6 @@ module JSON { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@json_ast_node node) { exists(@location_default loc | json_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -1860,7 +1857,6 @@ module JSON { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @json_ast_node node) { not isOverlay() and file = getNodeFile(node) } diff --git a/ql/ql/src/experimental/RA.qll b/ql/ql/src/experimental/RA.qll index 7187ebfc8c74..5eb804555620 100644 --- a/ql/ql/src/experimental/RA.qll +++ b/ql/ql/src/experimental/RA.qll @@ -1,6 +1,5 @@ -/** - * Parses RA expressions. - */ +overlay[local] +module; /** * A predicate that contains RA. diff --git a/ql/ql/src/queries/performance/LargeTupleSum.ql b/ql/ql/src/queries/performance/LargeTupleSum.ql index e5bbed79bbd3..4e5ca6622e80 100644 --- a/ql/ql/src/queries/performance/LargeTupleSum.ql +++ b/ql/ql/src/queries/performance/LargeTupleSum.ql @@ -6,6 +6,7 @@ import ql import codeql_ql.StructuredLogs import KindPredicatesLog +overlay[local] module SumCounts implements Fold { int base(PipeLineRun run) { result = sum(int i | | run.getCount(i)) } diff --git a/ql/ql/test/experimental/raparser.ql b/ql/ql/test/experimental/raparser.ql index 29489e2a968c..5704b0facdb4 100644 --- a/ql/ql/test/experimental/raparser.ql +++ b/ql/ql/test/experimental/raparser.ql @@ -1,5 +1,6 @@ import experimental.RA +overlay[local] class TestPredicate extends string { TestPredicate() { this = "p1" } diff --git a/ruby/ql/lib/change-notes/2025-07-09-overlay-local.md b/ruby/ql/lib/change-notes/2025-07-09-overlay-local.md new file mode 100644 index 000000000000..f1c7fe83a262 --- /dev/null +++ b/ruby/ql/lib/change-notes/2025-07-09-overlay-local.md @@ -0,0 +1,4 @@ +--- +category: breaking +--- +* Most classes and predicates in the AST, SSA, and control-flow-graph libraries are now annotated with `overlay[local]`, in preparation for incremental analysis. This could result in compiler errors for custom queries if they extend these classes. To mitigate such errors, look for ways to restructure custom QL code so it doesn't depend on changing the behavior of standard-library classes. diff --git a/ruby/ql/lib/codeql/Locations.qll b/ruby/ql/lib/codeql/Locations.qll index 148c6b01f2d9..df52d6822a2e 100644 --- a/ruby/ql/lib/codeql/Locations.qll +++ b/ruby/ql/lib/codeql/Locations.qll @@ -1,4 +1,6 @@ /** Provides classes for working with locations. */ +overlay[local] +module; import files.FileSystem diff --git a/ruby/ql/lib/codeql/files/FileSystem.qll b/ruby/ql/lib/codeql/files/FileSystem.qll index 528dde52fd91..6cc771fad9d2 100644 --- a/ruby/ql/lib/codeql/files/FileSystem.qll +++ b/ruby/ql/lib/codeql/files/FileSystem.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local] +module; private import codeql.Locations private import codeql.util.FileSystem diff --git a/ruby/ql/lib/codeql/ruby/AST.qll b/ruby/ql/lib/codeql/ruby/AST.qll index bd42696a8dbe..2c2dbdfa5322 100644 --- a/ruby/ql/lib/codeql/ruby/AST.qll +++ b/ruby/ql/lib/codeql/ruby/AST.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import codeql.Locations import ast.Call import ast.Control diff --git a/ruby/ql/lib/codeql/ruby/Diagnostics.qll b/ruby/ql/lib/codeql/ruby/Diagnostics.qll index 58de14b8fcf5..5b55eec38098 100644 --- a/ruby/ql/lib/codeql/ruby/Diagnostics.qll +++ b/ruby/ql/lib/codeql/ruby/Diagnostics.qll @@ -1,4 +1,6 @@ /** Provides classes relating to extraction diagnostics. */ +overlay[local] +module; private import codeql.Locations diff --git a/ruby/ql/lib/codeql/ruby/ast/Call.qll b/ruby/ql/lib/codeql/ruby/ast/Call.qll index 8a69ebd36fbb..10b23b22d55c 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Call.qll @@ -1,6 +1,10 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Call +private import internal.Literal private import internal.TreeSitter private import codeql.ruby.dataflow.internal.DataFlowDispatch private import codeql.ruby.dataflow.internal.DataFlowImplCommon @@ -41,7 +45,7 @@ class Call extends Expr instanceof CallImpl { final Expr getKeywordArgument(string keyword) { exists(Pair p | p = this.getAnArgument() and - p.getKey().getConstantValue().isSymbol(keyword) and + keyword = p.getKey().(SymbolLiteral).(StringlikeLiteralImpl).getStringValue() and result = p.getValue() ) } @@ -52,6 +56,7 @@ class Call extends Expr instanceof CallImpl { final int getNumberOfArguments() { result = super.getNumberOfArgumentsImpl() } /** Gets a potential target of this call, if any. */ + overlay[global] final Callable getATarget() { exists(DataFlowCall c | this = c.asCall().getExpr() and @@ -153,6 +158,7 @@ class MethodCall extends Call instanceof MethodCallImpl { * TODO: When API Graphs is able to resolve calls to methods like `Kernel.send` * this class is no longer necessary and should be removed. */ +overlay[global] class UnknownMethodCall extends MethodCall { UnknownMethodCall() { not exists(this.(Call).getATarget()) } } diff --git a/ruby/ql/lib/codeql/ruby/ast/Constant.qll b/ruby/ql/lib/codeql/ruby/ast/Constant.qll index fef057bc88ee..125aef4980fe 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Constant.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Constant.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Constant @@ -6,6 +9,7 @@ private import internal.Variable private import internal.TreeSitter /** A constant value. */ +overlay[global] class ConstantValue extends TConstantValue { /** Gets a textual representation of this constant value. */ final string toString() { this.hasValueWithType(result, _) } @@ -134,6 +138,7 @@ class ConstantValue extends TConstantValue { } /** Provides different sub classes of `ConstantValue`. */ +overlay[global] module ConstantValue { /** A constant integer value. */ class ConstantIntegerValue extends ConstantValue, TInt { } @@ -268,15 +273,18 @@ class ConstantReadAccess extends ConstantAccess { * * the value being read at `M::CONST` is `"const"`. */ + overlay[global] Expr getValue() { result = getConstantReadAccessValue(this) } /** * Gets a fully qualified name for this constant read, based on the context in * which it occurs. */ + overlay[global] string getAQualifiedName() { result = resolveConstant(this) } /** Gets the module that this read access resolves to, if any. */ + overlay[global] Module getModule() { result = resolveConstantReadAccess(this) } final override string getAPrimaryQlClass() { result = "ConstantReadAccess" } @@ -342,6 +350,7 @@ class ConstantWriteAccess extends ConstantAccess { * constants up the namespace chain, the fully qualified name of a nested * constant can be ambiguous from just statically looking at the AST. */ + overlay[global] string getAQualifiedName() { result = resolveConstantWrite(this) } } diff --git a/ruby/ql/lib/codeql/ruby/ast/Control.qll b/ruby/ql/lib/codeql/ruby/ast/Control.qll index 18182d8268ac..5d83e7a62fd2 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Control.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Control.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Control diff --git a/ruby/ql/lib/codeql/ruby/ast/Erb.qll b/ruby/ql/lib/codeql/ruby/ast/Erb.qll index 4dbcca734254..4def19f7ceb5 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Erb.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Erb.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.Erb private import internal.TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/Expr.qll b/ruby/ql/lib/codeql/ruby/ast/Expr.qll index 5f916fbec5cf..e932202e53fd 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Expr.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Expr.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import internal.AST @@ -12,6 +15,7 @@ private import internal.TreeSitter */ class Expr extends Stmt, TExpr { /** Gets the constant value of this expression, if any. */ + overlay[global] ConstantValue getConstantValue() { result = getConstantValueExpr(this) } } @@ -425,6 +429,7 @@ class StringConcatenation extends Expr, TStringConcatenation { * "foo" "bar#{ n }" * ``` */ + overlay[global] final string getConcatenatedValueText() { forall(StringLiteral c | c = this.getString(_) | exists(c.getConstantValue().getStringlikeValue()) diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll index cdeae9e64a6e..308b2a9667cb 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.Regexp as RE private import internal.AST @@ -41,6 +44,7 @@ class IntegerLiteral extends NumericLiteral instanceof IntegerLiteralImpl { /** Gets the numerical value of this integer literal. */ final int getValue() { result = super.getValue() } + overlay[global] final override ConstantValue::ConstantIntegerValue getConstantValue() { result = NumericLiteral.super.getConstantValue() } @@ -57,6 +61,7 @@ class IntegerLiteral extends NumericLiteral instanceof IntegerLiteralImpl { * ``` */ class FloatLiteral extends NumericLiteral instanceof FloatLiteralImpl { + overlay[global] final override ConstantValue::ConstantFloatValue getConstantValue() { result = NumericLiteral.super.getConstantValue() } @@ -72,6 +77,7 @@ class FloatLiteral extends NumericLiteral instanceof FloatLiteralImpl { * ``` */ class RationalLiteral extends NumericLiteral instanceof RationalLiteralImpl { + overlay[global] final override ConstantValue::ConstantRationalValue getConstantValue() { result = NumericLiteral.super.getConstantValue() } @@ -87,6 +93,7 @@ class RationalLiteral extends NumericLiteral instanceof RationalLiteralImpl { * ``` */ class ComplexLiteral extends NumericLiteral instanceof ComplexLiteralImpl { + overlay[global] final override ConstantValue::ConstantComplexValue getConstantValue() { result = NumericLiteral.super.getConstantValue() } @@ -96,6 +103,7 @@ class ComplexLiteral extends NumericLiteral instanceof ComplexLiteralImpl { /** A `nil` literal. */ class NilLiteral extends Literal instanceof NilLiteralImpl { + overlay[global] final override ConstantValue::ConstantNilValue getConstantValue() { result = TNil() } final override string getAPrimaryQlClass() { result = "NilLiteral" } @@ -122,6 +130,7 @@ class BooleanLiteral extends Literal instanceof BooleanLiteralImpl { /** Gets the value of this Boolean literal. */ boolean getValue() { result = super.getValue() } + overlay[global] final override ConstantValue::ConstantBooleanValue getConstantValue() { result = Literal.super.getConstantValue() } @@ -133,6 +142,7 @@ class BooleanLiteral extends Literal instanceof BooleanLiteralImpl { class EncodingLiteral extends Literal instanceof EncodingLiteralImpl { final override string getAPrimaryQlClass() { result = "EncodingLiteral" } + overlay[global] final override ConstantValue::ConstantStringValue getConstantValue() { result = Literal.super.getConstantValue() } @@ -144,6 +154,7 @@ class EncodingLiteral extends Literal instanceof EncodingLiteralImpl { class LineLiteral extends Literal instanceof LineLiteralImpl { final override string getAPrimaryQlClass() { result = "LineLiteral" } + overlay[global] final override ConstantValue::ConstantIntegerValue getConstantValue() { result = Literal.super.getConstantValue() } @@ -155,6 +166,7 @@ class LineLiteral extends Literal instanceof LineLiteralImpl { class FileLiteral extends Literal instanceof FileLiteralImpl { final override string getAPrimaryQlClass() { result = "FileLiteral" } + overlay[global] final override ConstantValue::ConstantStringValue getConstantValue() { result = Literal.super.getConstantValue() } @@ -166,6 +178,7 @@ class FileLiteral extends Literal instanceof FileLiteralImpl { */ class StringComponent extends AstNode instanceof StringComponentImpl { /** Gets the constant value of this string component, if any. */ + overlay[global] ConstantValue::ConstantStringValue getConstantValue() { result = TString(super.getValue()) } } @@ -210,6 +223,7 @@ class StringInterpolationComponent extends StringComponent, StmtSequence instanc final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) } + overlay[global] final override ConstantValue::ConstantStringValue getConstantValue() { result = StmtSequence.super.getConstantValue() } @@ -257,6 +271,7 @@ class RegExpInterpolationComponent extends RegExpComponent, StmtSequence instanc final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) } + overlay[global] final override ConstantValue::ConstantStringValue getConstantValue() { result = StmtSequence.super.getConstantValue() } @@ -387,6 +402,7 @@ class RegExpLiteral extends StringlikeLiteral instanceof RegExpLiteralImpl { final predicate hasFreeSpacingFlag() { this.getFlagString().charAt(_) = "x" } /** Returns the root node of the parse tree of this regular expression. */ + overlay[global] final RE::RegExpTerm getParsed() { result = RE::getParsedRegExp(this) } } @@ -404,6 +420,7 @@ class SymbolLiteral extends StringlikeLiteral instanceof SymbolLiteralImpl { not this instanceof MethodName and result = "SymbolLiteral" } + overlay[global] final override ConstantValue::ConstantSymbolValue getConstantValue() { result = StringlikeLiteral.super.getConstantValue() } @@ -436,6 +453,7 @@ class SubshellLiteral extends StringlikeLiteral instanceof SubshellLiteralImpl { class CharacterLiteral extends Literal instanceof CharacterLiteralImpl { final override string getAPrimaryQlClass() { result = "CharacterLiteral" } + overlay[global] final override ConstantValue::ConstantStringValue getConstantValue() { result = Literal.super.getConstantValue() } diff --git a/ruby/ql/lib/codeql/ruby/ast/Method.qll b/ruby/ql/lib/codeql/ruby/ast/Method.qll index 61ee58019d1e..147782e3d08d 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Method.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Method.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.controlflow.ControlFlowGraph private import internal.AST @@ -40,18 +43,22 @@ class MethodBase extends Callable, BodyStmt, Scope, TMethodBase { * Holds if this method is public. * Methods are public by default. */ + overlay[global] predicate isPublic() { this.getVisibility() = "public" } /** Holds if this method is private. */ + overlay[global] predicate isPrivate() { this.getVisibility() = "private" } /** Holds if this method is protected. */ + overlay[global] predicate isProtected() { this.getVisibility() = "protected" } /** * Gets a string describing the visibility of this method. * This is either 'public', 'private' or 'protected'. */ + overlay[global] string getVisibility() { result = getVisibilityModifier(this).getVisibility() or @@ -73,6 +80,7 @@ class MethodBase extends Callable, BodyStmt, Scope, TMethodBase { * end * ``` */ +overlay[global] private VisibilityModifier getExplicitVisibilityModifier(Method m) { result.getMethodArgument() = m or @@ -86,6 +94,7 @@ private VisibilityModifier getExplicitVisibilityModifier(Method m) { * Gets the visibility modifier that defines the visibility of method `m`, if * any. */ +overlay[global] private VisibilityModifier getVisibilityModifier(MethodBase mb) { mb = any(Method m | @@ -202,6 +211,7 @@ class Method extends MethodBase, TMethod { * end * ``` */ + overlay[global] override predicate isPrivate() { super.isPrivate() } final override Parameter getParameter(int n) { @@ -210,6 +220,7 @@ class Method extends MethodBase, TMethod { final override string toString() { result = this.getName() } + overlay[global] override string getVisibility() { result = getVisibilityModifier(this).getVisibility() or @@ -223,6 +234,7 @@ class Method extends MethodBase, TMethod { } } +overlay[global] pragma[nomagic] private predicate modifiesIn(VisibilityModifier vm, ModuleBase n, string name) { n = vm.getEnclosingModule() and @@ -299,6 +311,7 @@ class SingletonMethod extends MethodBase, TSingletonMethod { * end * ``` */ + overlay[global] override predicate isPrivate() { super.isPrivate() } } diff --git a/ruby/ql/lib/codeql/ruby/ast/Module.qll b/ruby/ql/lib/codeql/ruby/ast/Module.qll index 9e2ca31ee61e..90ee8275f397 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Module.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import internal.AST @@ -8,6 +11,7 @@ private import internal.Scope /** * A representation of a run-time `module` or `class` value. */ +overlay[global] class Module extends TModule { /** Gets a declaration of this module, if any. */ ModuleBase getADeclaration() { result.getModule() = this } @@ -255,6 +259,7 @@ class ModuleBase extends BodyStmt, Scope, TModuleBase { } /** Gets the representation of the run-time value of this module or class. */ + overlay[global] Module getModule() { none() } /** @@ -333,6 +338,7 @@ class Toplevel extends ModuleBase, TToplevel { pred = "getBeginBlock" and result = this.getBeginBlock(_) } + overlay[global] final override Module getModule() { result = TResolved("Object") } final override string toString() { result = g.getLocation().getFile().getBaseName() } @@ -405,6 +411,7 @@ class Namespace extends ModuleBase, ConstantWriteAccess, TNamespace { */ override predicate hasGlobalScope() { none() } + overlay[global] final override Module getModule() { result = any(string qName | qName = namespaceDeclaration(this) | TResolved(qName)) or diff --git a/ruby/ql/lib/codeql/ruby/ast/Operation.qll b/ruby/ql/lib/codeql/ruby/ast/Operation.qll index 2e005a207e3f..b9046a930b31 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Operation.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Operation.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll index c4b233b62b6e..5b3994378c16 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Variable diff --git a/ruby/ql/lib/codeql/ruby/ast/Pattern.qll b/ruby/ql/lib/codeql/ruby/ast/Pattern.qll index ef7786640313..ac6bcc712cf9 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Pattern.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Pattern.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Pattern @@ -203,6 +206,7 @@ class HashPattern extends CasePattern, THashPattern { } /** Gets the value for a given key name. */ + overlay[global] CasePattern getValueByKey(string key) { exists(int i | this.getKey(i).getConstantValue().isStringlikeValue(key) and result = this.getValue(i) diff --git a/ruby/ql/lib/codeql/ruby/ast/Scope.qll b/ruby/ql/lib/codeql/ruby/ast/Scope.qll index 3e8437f79b35..334b36b583f3 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Scope.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Scope.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Scope diff --git a/ruby/ql/lib/codeql/ruby/ast/Statement.qll b/ruby/ql/lib/codeql/ruby/ast/Statement.qll index 24e18fe4c362..dcd51dbb3272 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Statement.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Statement.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/Variable.qll b/ruby/ql/lib/codeql/ruby/ast/Variable.qll index fa00cfb4cc7c..f5fb4b606046 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Variable.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Variable.qll @@ -1,4 +1,6 @@ /** Provides classes for modeling program variables. */ +overlay[local] +module; private import codeql.ruby.AST private import internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll index badcf1d6c6ff..ee46fbe8b66a 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import codeql.Locations private import TreeSitter private import codeql.ruby.ast.internal.Call diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll index 5bb34989a904..4f3c236f1024 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Call.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import Variable private import codeql.ruby.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll index a04efc1ec94f..6fdcdc894182 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Constant.qll @@ -38,6 +38,7 @@ private import ExprNodes * constant value in some cases. */ private module Propagation { + overlay[local] ExprCfgNode getSource(VariableReadAccessCfgNode read) { exists(Ssa::WriteDefinition def | def.assigns(result) and @@ -199,6 +200,7 @@ private module Propagation { forex(ExprCfgNode n | n = e.getAControlFlowNode() | isComplex(n, real, imaginary)) } + overlay[local] private class StringlikeLiteralWithInterpolationCfgNode extends StringlikeLiteralCfgNode { StringlikeLiteralWithInterpolationCfgNode() { this.getAComponent() = @@ -208,6 +210,7 @@ private module Propagation { ) } + overlay[global] pragma[nomagic] private string getComponentValue(int i) { this.getComponent(i) = @@ -219,17 +222,20 @@ private module Propagation { } language[monotonicAggregates] + overlay[global] private string getValue() { result = strictconcat(int i | exists(this.getComponent(i)) | this.getComponentValue(i) order by i) } + overlay[global] pragma[nomagic] string getSymbolValue() { result = this.getValue() and this.getExpr() instanceof SymbolLiteral } + overlay[global] pragma[nomagic] string getStringValue() { result = this.getValue() and @@ -237,6 +243,7 @@ private module Propagation { not this.getExpr() instanceof RegExpLiteral } + overlay[global] pragma[nomagic] string getRegExpValue(string flags) { result = this.getValue() and @@ -566,6 +573,7 @@ private predicate isArrayExpr(Expr e, ArrayLiteralCfgNode arr) { isArrayExpr(e.(MethodCall).getReceiver(), arr) } +overlay[local] private class TokenConstantAccess extends ConstantAccess, TTokenConstantAccess { private Ruby::Constant g; @@ -577,6 +585,7 @@ private class TokenConstantAccess extends ConstantAccess, TTokenConstantAccess { /** * A constant access that has a scope resolution qualifier. */ +overlay[local] class ScopeResolutionConstantAccess extends ConstantAccess, TScopeResolutionConstantAccess { private Ruby::ScopeResolution g; private Ruby::Constant constant; @@ -595,6 +604,7 @@ class ScopeResolutionConstantAccess extends ConstantAccess, TScopeResolutionCons final override predicate hasGlobalScope() { not exists(g.getScope()) } } +overlay[local] private class ConstantReadAccessSynth extends ConstantAccess, TConstantReadAccessSynth { private string value; @@ -609,6 +619,7 @@ private class ConstantReadAccessSynth extends ConstantAccess, TConstantReadAcces final override predicate hasGlobalScope() { value.matches("::%") } } +overlay[local] private class ConstantWriteAccessSynth extends ConstantAccess, TConstantWriteAccessSynth { private string value; diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll index 7b95d67efc45..dd57a0d197de 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Control.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll index 7a69bf5b783d..29960486907b 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Erb.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import codeql.Locations private import TreeSitter private import codeql.ruby.ast.Erb diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll index ba4f9e51f4e9..fdeec446a937 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.CFG private import AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll index 8af4673d9168..6a2df06b3490 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Literal.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import Constant diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll index 075ac5fb8fa9..c4dd1abbee02 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Method.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll index 6905dd5ff2d1..3670cc5eb98e 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import Scope as Scope @@ -11,6 +14,7 @@ private string builtin() { ] } +overlay[global] cached private module Cached { cached @@ -215,6 +219,7 @@ private string scopeAppend(string qualifier, string name) { * both as a performance optimization (minimize non-linear recursion), and as a way * to prevent infinite recursion. */ +overlay[global] private module ResolveImpl { private ModuleBase enclosing(ModuleBase m, int level) { result = m and level = 0 @@ -583,6 +588,7 @@ private ModuleBase enclosingModuleNoBlock(Stmt node) { result = enclosingScopesNoBlock(Scope::scopeOfInclSynth(node)) } +overlay[global] private Module getAncestors(Module m) { result = m or result = getAncestors(m.getAnIncludedModule()) or @@ -593,6 +599,7 @@ private newtype TMethodOrExpr = TMethod(Method m) or TExpr(Expr e) +overlay[global] private TMethodOrExpr getMethodOrConst(TModule owner, string name) { exists(ModuleBase m | m.getModule() = owner | result = TMethod(m.getMethod(name)) @@ -601,12 +608,14 @@ private TMethodOrExpr getMethodOrConst(TModule owner, string name) { ) } +overlay[global] module ExposedForTestingOnly { Method getMethod(TModule owner, string name) { TMethod(result) = getMethodOrConst(owner, name) } Expr getConst(TModule owner, string name) { TExpr(result) = getMethodOrConst(owner, name) } } +overlay[global] private TMethodOrExpr lookupMethodOrConst0(Module m, string name) { result = lookupMethodOrConst0(m.getAPrependedModule(), name) or @@ -621,6 +630,7 @@ private TMethodOrExpr lookupMethodOrConst0(Module m, string name) { private AstNode getNode(TMethodOrExpr e) { e = TMethod(result) or e = TExpr(result) } +overlay[global] private TMethodOrExpr lookupMethodOrConst(Module m, string name) { result = lookupMethodOrConst0(m, name) or diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll index 54c763e24d39..eeec2198b625 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll index dc7fb8c7695e..8f07554fb0c1 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll index c59898d88eeb..a30cce32c7c6 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import codeql.ruby.ast.internal.Expr private import codeql.ruby.ast.internal.Parameter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll index 8f5bde5aeecb..9ec237012bc2 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Scope.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll index 5d1ee81c0139..f2be91a63e51 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll @@ -1,4 +1,6 @@ /** Provides predicates for synthesizing AST nodes. */ +overlay[local] +module; private import AST private import TreeSitter diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll b/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll index 4d9cd901f237..dbc7b38b84e3 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll @@ -23,6 +23,7 @@ private predicate discardLocation(@location_default loc) { ) } +overlay[local] module Ruby { /** The base class for all AST nodes */ class AstNode extends @ruby_ast_node { @@ -67,7 +68,6 @@ module Ruby { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@ruby_ast_node node) { exists(@location_default loc | ruby_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -75,7 +75,6 @@ module Ruby { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @ruby_ast_node node) { not isOverlay() and file = getNodeFile(node) } @@ -1967,6 +1966,7 @@ module Ruby { } } +overlay[local] module Erb { /** The base class for all AST nodes */ class AstNode extends @erb_ast_node { @@ -2011,7 +2011,6 @@ module Erb { } /** Gets the file containing the given `node`. */ - overlay[local] private @file getNodeFile(@erb_ast_node node) { exists(@location_default loc | erb_ast_node_location(node, loc) | locations_default(loc, result, _, _, _, _) @@ -2019,7 +2018,6 @@ module Erb { } /** Holds if `node` is in the `file` and is part of the overlay base database. */ - overlay[local] private predicate discardableAstNode(@file file, @erb_ast_node node) { not isOverlay() and file = getNodeFile(node) } diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll index bea1ddadbfb3..7c130220a86b 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Variable.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import TreeSitter private import codeql.ruby.AST private import codeql.ruby.CFG diff --git a/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll b/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll index f70062ad24f3..932533711984 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/BasicBlocks.qll @@ -1,4 +1,6 @@ /** Provides classes representing basic blocks. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll index c822450bf89c..0da31370ff01 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll @@ -1,10 +1,11 @@ /** Provides classes representing nodes in a control flow graph. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.controlflow.BasicBlocks private import codeql.ruby.dataflow.SSA private import codeql.ruby.ast.internal.Constant -private import codeql.ruby.ast.internal.Literal private import ControlFlowGraph private import internal.ControlFlowGraphImpl as CfgImpl @@ -36,11 +37,13 @@ class ExitNode extends CfgNode, CfgImpl::ExitNode { */ class AstCfgNode extends CfgNode, CfgImpl::AstCfgNode { /** Gets the name of the primary QL class for this node. */ + overlay[global] override string getAPrimaryQlClass() { result = "AstCfgNode" } } /** A control-flow node that wraps an AST expression. */ class ExprCfgNode extends AstCfgNode { + overlay[global] override string getAPrimaryQlClass() { result = "ExprCfgNode" } Expr e; @@ -51,6 +54,7 @@ class ExprCfgNode extends AstCfgNode { Expr getExpr() { result = e } /** Gets the constant value of this expression, if any. */ + overlay[global] ConstantValue getConstantValue() { result = getConstantValue(this) } } @@ -76,6 +80,7 @@ class StringComponentCfgNode extends AstCfgNode { StringComponentCfgNode() { this.getAstNode() instanceof StringComponent } /** Gets the constant value of this string component. */ + overlay[global] ConstantValue getConstantValue() { result = this.getAstNode().(StringComponent).getConstantValue() } @@ -297,6 +302,7 @@ module ExprNodes { /** A control-flow node that wraps a `Call` AST expression. */ class CallCfgNode extends ExprCfgNode { + overlay[global] override string getAPrimaryQlClass() { result = "CallCfgNode" } override CallExprChildMapping e; @@ -310,6 +316,7 @@ module ExprNodes { final ExprCfgNode getAnArgument() { result = this.getArgument(_) } /** Gets the keyword argument whose key is `keyword` of this call. */ + overlay[global] final ExprCfgNode getKeywordArgument(string keyword) { exists(PairCfgNode n | e.hasCfgChild(e.getAnArgument(), this, n) and @@ -338,6 +345,7 @@ module ExprNodes { /** A control-flow node that wraps a `MethodCall` AST expression. */ class MethodCallCfgNode extends CallCfgNode { + overlay[global] override string getAPrimaryQlClass() { result = "MethodCallCfgNode" } MethodCallCfgNode() { super.getExpr() instanceof MethodCall } @@ -842,6 +850,7 @@ module ExprNodes { this.getAstNode() instanceof StringInterpolationComponent } + overlay[global] final override ConstantValue getConstantValue() { result = StmtSequenceCfgNode.super.getConstantValue() } @@ -855,6 +864,7 @@ module ExprNodes { this.getAstNode() instanceof RegExpInterpolationComponent } + overlay[global] final override ConstantValue getConstantValue() { result = StmtSequenceCfgNode.super.getConstantValue() } @@ -946,6 +956,7 @@ module ExprNodes { * into calls to `Array.[]`, so this includes both desugared calls as well as * explicit calls. */ + overlay[global] class ArrayLiteralCfgNode extends MethodCallCfgNode { override string getAPrimaryQlClass() { result = "ArrayLiteralCfgNode" } @@ -963,6 +974,7 @@ module ExprNodes { * into calls to `Hash.[]`, so this includes both desugared calls as well as * explicit calls. */ + overlay[global] class HashLiteralCfgNode extends MethodCallCfgNode { override string getAPrimaryQlClass() { result = "HashLiteralCfgNode" } diff --git a/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll b/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll index dee31d8e901b..1d3632ba1c07 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/ControlFlowGraph.qll @@ -1,4 +1,6 @@ /** Provides classes representing the control flow graph. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.controlflow.BasicBlocks @@ -35,6 +37,7 @@ class CfgScope extends Scope instanceof CfgImpl::CfgScopeImpl { */ class CfgNode extends CfgImpl::Node { /** Gets the name of the primary QL class for this node. */ + overlay[global] string getAPrimaryQlClass() { none() } /** Gets the file of this control flow node. */ diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll index 83ea11e9d230..b8edf83c20df 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Completion.qll @@ -3,6 +3,8 @@ * * A completion represents how a statement or expression terminates. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.ast.internal.AST diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll index dd672ba982d7..d0d418a839f6 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll @@ -2,6 +2,8 @@ * Provides an implementation for constructing control-flow graphs (CFGs) from * abstract syntax trees (ASTs), using the shared library from `codeql.controlflow.Cfg`. */ +overlay[local] +module; private import codeql.controlflow.Cfg as CfgShared private import codeql.ruby.AST diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll index 1161a061581c..a60102e017c6 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Guards.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.CFG /** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */ diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll index e1927a0b1c97..45b299a5d2b7 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/NonReturning.qll @@ -1,4 +1,6 @@ /** Provides a simple analysis for identifying calls that will not return. */ +overlay[local] +module; private import codeql.ruby.AST private import Completion diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll index 5331a3d26b64..146d5927479d 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates relevant for splitting the control flow graph. */ +overlay[local] +module; private import codeql.ruby.AST as Ast private import Completion as Comp diff --git a/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll b/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll index 07721d333341..1478d9ed9d6b 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/SSA.qll @@ -1,6 +1,8 @@ /** * Provides the module `Ssa` for working with static single assignment (SSA) form. */ +overlay[local] +module; /** * Provides classes for working with static single assignment (SSA) form. diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll index adbec18be640..3e1d27a17ba0 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/SsaImpl.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ssa.Ssa as SsaImplCommon private import codeql.ruby.AST private import codeql.ruby.CFG as Cfg @@ -393,6 +396,7 @@ private module Cached { signature predicate guardChecksSig(Cfg::CfgNodes::AstCfgNode g, Cfg::CfgNode e, boolean branch); + overlay[global] cached // nothing is actually cached module BarrierGuard { private predicate guardChecksAdjTypes( diff --git a/shared/tree-sitter-extractor/src/generator/mod.rs b/shared/tree-sitter-extractor/src/generator/mod.rs index d9e6e00a1211..5e58611092b2 100644 --- a/shared/tree-sitter-extractor/src/generator/mod.rs +++ b/shared/tree-sitter-extractor/src/generator/mod.rs @@ -120,6 +120,7 @@ pub fn generate( qldoc: None, name: &language.name, body, + overlay: Some(ql::OverlayAnnotation::Local), })], )?; } diff --git a/shared/tree-sitter-extractor/src/generator/ql.rs b/shared/tree-sitter-extractor/src/generator/ql.rs index e4c87b61bdb8..b1e319afb1e8 100644 --- a/shared/tree-sitter-extractor/src/generator/ql.rs +++ b/shared/tree-sitter-extractor/src/generator/ql.rs @@ -95,6 +95,7 @@ pub struct Module<'a> { pub qldoc: Option, pub name: &'a str, pub body: Vec>, + pub overlay: Option, } impl fmt::Display for Module<'_> { @@ -102,6 +103,14 @@ impl fmt::Display for Module<'_> { if let Some(qldoc) = &self.qldoc { write!(f, "/** {} */", qldoc)?; } + if let Some(overlay_annotation) = &self.overlay { + write!(f, "overlay[")?; + match overlay_annotation { + OverlayAnnotation::Local => write!(f, "local")?, + OverlayAnnotation::DiscardEntity => write!(f, "discard_entity")?, + } + write!(f, "] ")?; + } writeln!(f, "module {} {{ ", self.name)?; for decl in &self.body { writeln!(f, " {}", decl)?; diff --git a/shared/tree-sitter-extractor/src/generator/ql_gen.rs b/shared/tree-sitter-extractor/src/generator/ql_gen.rs index 8b6c9c18c6f8..2cfaf5715caa 100644 --- a/shared/tree-sitter-extractor/src/generator/ql_gen.rs +++ b/shared/tree-sitter-extractor/src/generator/ql_gen.rs @@ -286,7 +286,7 @@ pub fn create_get_node_file_predicate<'a>( overridden: false, is_private: true, is_final: false, - overlay: Some(ql::OverlayAnnotation::Local), + overlay: None, return_type: Some(ql::Type::At("file")), formal_parameters: vec![ql::FormalParameter { name: "node", @@ -327,7 +327,7 @@ pub fn create_discardable_ast_node_predicate(ast_node_name: &str) -> ql::Predica overridden: false, is_private: true, is_final: false, - overlay: Some(ql::OverlayAnnotation::Local), + overlay: None, return_type: None, formal_parameters: vec![ ql::FormalParameter {