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/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..ab7a0603b670 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Call.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Call.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import codeql.ruby.AST private import internal.AST private import internal.Call @@ -38,6 +41,7 @@ class Call extends Expr instanceof CallImpl { * foo :bar "baz", qux: 123 * ``` */ + overlay[global] final Expr getKeywordArgument(string keyword) { exists(Pair p | p = this.getAnArgument() and @@ -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..2a3d23056f4e 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll @@ -1,4 +1,6 @@ /** Provides classes representing nodes in a control flow graph. */ +overlay[local] +module; private import codeql.ruby.AST private import codeql.ruby.controlflow.BasicBlocks @@ -36,11 +38,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 +55,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 +81,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 +303,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 +317,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 +346,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 +851,7 @@ module ExprNodes { this.getAstNode() instanceof StringInterpolationComponent } + overlay[global] final override ConstantValue getConstantValue() { result = StmtSequenceCfgNode.super.getConstantValue() } @@ -855,6 +865,7 @@ module ExprNodes { this.getAstNode() instanceof RegExpInterpolationComponent } + overlay[global] final override ConstantValue getConstantValue() { result = StmtSequenceCfgNode.super.getConstantValue() } @@ -946,6 +957,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 +975,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..5d69810ed9a1 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 @@ -375,10 +378,12 @@ private module Cached { Impl::uncertainWriteDefinitionInput(def, result) } + overlay[global] cached module DataFlowIntegration { import DataFlowIntegrationImpl + overlay[local] cached predicate localFlowStep( SsaInput::SourceVariable v, Node nodeFrom, Node nodeTo, boolean isUseStep @@ -469,19 +474,24 @@ class ParameterExt extends TParameterExt { } } +overlay[global] private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig { private import codeql.ruby.controlflow.internal.Guards as Guards + overlay[local] class Expr extends Cfg::CfgNodes::ExprCfgNode { predicate hasCfgNode(SsaInput::BasicBlock bb, int i) { this = bb.getNode(i) } } + overlay[local] Expr getARead(Definition def) { result = Cached::getARead(def) } + overlay[local] predicate ssaDefHasSource(WriteDefinition def) { any(ParameterExt p).isInitializedBy(def) or def.(Ssa::WriteDefinition).assigns(_) } + overlay[local] class Guard extends Cfg::CfgNodes::AstCfgNode { /** * Holds if the evaluation of this guard to `branch` corresponds to the edge @@ -506,6 +516,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu } /** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */ + overlay[local] predicate guardDirectlyControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) { Guards::guardControlsBlock(guard, bb, branch) } diff --git a/ruby/ql/lib/qlpack.yml b/ruby/ql/lib/qlpack.yml index ef9f163cbd91..9a1fd81630ed 100644 --- a/ruby/ql/lib/qlpack.yml +++ b/ruby/ql/lib/qlpack.yml @@ -17,3 +17,4 @@ dataExtensions: - codeql/ruby/frameworks/**/model.yml - codeql/ruby/frameworks/**/*.model.yml warnOnImplicitThis: true +compileForOverlayEval: true 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 {