diff --git a/javascript/ql/lib/Customizations.qll b/javascript/ql/lib/Customizations.qll index 724d52dcce63..08365d667df7 100644 --- a/javascript/ql/lib/Customizations.qll +++ b/javascript/ql/lib/Customizations.qll @@ -8,5 +8,7 @@ * `FileSystemAccess`, or the `Source` and `Sink` classes associated with the security queries * to model frameworks that are not covered by the standard library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/Declarations/Declarations.qll b/javascript/ql/lib/Declarations/Declarations.qll index 4fb60140af06..eeff76726b9a 100644 --- a/javascript/ql/lib/Declarations/Declarations.qll +++ b/javascript/ql/lib/Declarations/Declarations.qll @@ -2,6 +2,8 @@ * Provides predicates for finding variable references and declarations * in a given function or toplevel. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/Declarations/UnusedVariable.qll b/javascript/ql/lib/Declarations/UnusedVariable.qll index eb02f99444cf..4dc30e39327b 100644 --- a/javascript/ql/lib/Declarations/UnusedVariable.qll +++ b/javascript/ql/lib/Declarations/UnusedVariable.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for the 'js/unused-local-variable' query. */ +overlay[local?] +module; import javascript import LanguageFeatures.UnusedIndexVariable diff --git a/javascript/ql/lib/Expressions/DOMProperties.qll b/javascript/ql/lib/Expressions/DOMProperties.qll index fdb7e6024c27..a3b888aeda70 100644 --- a/javascript/ql/lib/Expressions/DOMProperties.qll +++ b/javascript/ql/lib/Expressions/DOMProperties.qll @@ -1,6 +1,8 @@ /** * Provides predicates for working with the DOM type hierarchy. */ +overlay[local?] +module; import semmle.javascript.Externs diff --git a/javascript/ql/lib/Expressions/ExprHasNoEffect.qll b/javascript/ql/lib/Expressions/ExprHasNoEffect.qll index 9813d9b32ed9..5e194b3fc3a5 100644 --- a/javascript/ql/lib/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/lib/Expressions/ExprHasNoEffect.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for the 'js/useless-expression' query. */ +overlay[local] +module; import javascript import DOMProperties @@ -60,6 +62,7 @@ predicate isDeclaration(Expr e) { /** * Holds if there exists a getter for a property called `name` anywhere in the program. */ +overlay[global] predicate isGetterProperty(string name) { // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | @@ -85,6 +88,7 @@ predicate isGetterProperty(string name) { /** * A property access that may invoke a getter. */ +overlay[global] class GetterPropertyAccess extends PropAccess { override predicate isImpure() { isGetterProperty(this.getPropertyName()) } } @@ -123,6 +127,7 @@ predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { * even if they do, the call itself is useless and should be flagged by this * query. */ +overlay[global] predicate noSideEffects(Expr e) { e.isPure() or @@ -148,6 +153,7 @@ predicate isCompoundExpression(Expr e) { /** * Holds if the expression `e` should be reported as having no effect. */ +overlay[global] predicate hasNoEffect(Expr e) { noSideEffects(e) and inVoidContext(e) and diff --git a/javascript/ql/lib/IDEContextual.qll b/javascript/ql/lib/IDEContextual.qll index f26956bcca01..e74d51898e8d 100644 --- a/javascript/ql/lib/IDEContextual.qll +++ b/javascript/ql/lib/IDEContextual.qll @@ -1,6 +1,8 @@ /** * Provides shared predicates related to contextual queries in the code viewer. */ +overlay[local?] +module; import semmle.files.FileSystem private import codeql.util.FileSystem diff --git a/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll b/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll index ed53158d51c9..c9905d98fccc 100644 --- a/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll +++ b/javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll @@ -1,6 +1,8 @@ /** * Provides a predicate for identifying unused index variables in loops. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/default.qll b/javascript/ql/lib/default.qll index 204a15864c3e..d123ec1a5983 100644 --- a/javascript/ql/lib/default.qll +++ b/javascript/ql/lib/default.qll @@ -3,5 +3,7 @@ * * Provides classes for working with JavaScript programs, as well as JSON, YAML and HTML. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/definitions.qll b/javascript/ql/lib/definitions.qll index 54ad0c3548a6..87018229e926 100644 --- a/javascript/ql/lib/definitions.qll +++ b/javascript/ql/lib/definitions.qll @@ -2,6 +2,8 @@ * Provides classes and predicates related to jump-to-definition links * in the code viewer. */ +overlay[local?] +module; import javascript import IDEContextual diff --git a/javascript/ql/lib/external/ExternalArtifact.qll b/javascript/ql/lib/external/ExternalArtifact.qll index 5d8a2ac9e6ff..c9b6410da602 100644 --- a/javascript/ql/lib/external/ExternalArtifact.qll +++ b/javascript/ql/lib/external/ExternalArtifact.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with external data. */ +overlay[local?] +module; import semmle.javascript.Locations diff --git a/javascript/ql/lib/javascript.qll b/javascript/ql/lib/javascript.qll index ad9cfe009b51..816096fc8275 100644 --- a/javascript/ql/lib/javascript.qll +++ b/javascript/ql/lib/javascript.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JavaScript programs, as well as JSON, YAML and HTML. */ +overlay[local?] +module; import Customizations import semmle.javascript.Aliases diff --git a/javascript/ql/lib/semmle/files/FileSystem.qll b/javascript/ql/lib/semmle/files/FileSystem.qll index 257f38c5e948..9947637b41e6 100644 --- a/javascript/ql/lib/semmle/files/FileSystem.qll +++ b/javascript/ql/lib/semmle/files/FileSystem.qll @@ -1,3 +1,5 @@ /** Provides classes for working with files and folders. */ +overlay[local?] +module; import semmle.javascript.Files diff --git a/javascript/ql/lib/semmle/javascript/AMD.qll b/javascript/ql/lib/semmle/javascript/AMD.qll index 4828aff27cc4..e66a04ce4ecd 100644 --- a/javascript/ql/lib/semmle/javascript/AMD.qll +++ b/javascript/ql/lib/semmle/javascript/AMD.qll @@ -2,6 +2,8 @@ * Provides classes for working with * [Asynchronous Module Definitions](https://github.com/amdjs/amdjs-api/wiki/AMD). */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -62,9 +64,11 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range } /** DEPRECATED. Use `getDependencyExpr` instead. */ + overlay[global] deprecated PathExpr getDependency(int i) { result = this.getDependencyExpr(i) } /** DEPRECATED. Use `getADependencyExpr` instead. */ + overlay[global] deprecated PathExpr getADependency() { result = this.getADependencyExpr() } /** Gets the `i`th dependency of this module definition. */ @@ -194,16 +198,19 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range * Gets an abstract value representing one or more values that may flow * into this module's `module.exports` property. */ + overlay[global] DefiniteAbstractValue getAModuleExportsValue() { result = [this.getAnImplicitExportsValue(), this.getAnExplicitExportsValue()] } + overlay[global] pragma[noinline, nomagic] private AbstractValue getAnImplicitExportsValue() { // implicit exports: anything that is returned from the factory function result = this.getModuleExpr().analyze().getAValue() } + overlay[global] pragma[noinline] private AbstractValue getAnExplicitExportsValue() { // explicit exports: anything assigned to `module.exports` @@ -227,6 +234,7 @@ class AmdModuleDefinition extends CallExpr instanceof AmdModuleDefinition::Range private predicate isPseudoDependency(string s) { s = ["exports", "require", "module"] } /** An AMD dependency, considered as a path expression. */ +overlay[global] private class AmdDependencyPath extends PathExprCandidate { AmdDependencyPath() { exists(AmdModuleDefinition amd | @@ -239,6 +247,7 @@ private class AmdDependencyPath extends PathExprCandidate { } /** A constant path element appearing in an AMD dependency expression. */ +overlay[global] deprecated private class ConstantAmdDependencyPathElement extends PathExpr, ConstantString { ConstantAmdDependencyPathElement() { this = any(AmdDependencyPath amd).getAPart() } @@ -281,6 +290,7 @@ private class AmdDependencyImport extends Import { * Specifically, we look for files whose absolute path ends with the imported path, possibly * adding well-known JavaScript file extensions like `.js`. */ + overlay[global] private File guessTarget() { exists(FilePath imported, string abspath, string dirname, string basename | this.targetCandidate(result, abspath, imported, dirname, basename) @@ -303,6 +313,7 @@ private class AmdDependencyImport extends Import { * Additionally, `abspath` is bound to the absolute path of `f`, `imported` to the imported path, and * `dirname` and `basename` to the dirname and basename (respectively) of `imported`. */ + overlay[global] private predicate targetCandidate( File f, string abspath, FilePath imported, string dirname, string basename ) { @@ -316,10 +327,12 @@ private class AmdDependencyImport extends Import { /** * Gets the module whose absolute path matches this import, if there is only a single such module. */ + overlay[global] private Module resolveByAbsolutePath() { result.getFile() = unique(File file | file = this.guessTarget()) } + overlay[global] override Module getImportedModule() { result = super.getImportedModule() or @@ -348,14 +361,12 @@ private class AmdDependencyImport extends Import { */ class AmdModule extends Module { cached - AmdModule() { - Stages::DataFlowStage::ref() and - exists(unique(AmdModuleDefinition def | amdModuleTopLevel(def, this))) - } + AmdModule() { exists(unique(AmdModuleDefinition def | amdModuleTopLevel(def, this))) } /** Gets the definition of this module. */ AmdModuleDefinition getDefine() { amdModuleTopLevel(result, this) } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { exists(DataFlow::PropWrite pwn | result = pwn.getRhs() | pwn.getBase().analyze().getAValue() = this.getDefine().getAModuleExportsValue() and @@ -363,6 +374,7 @@ class AmdModule extends Module { ) } + overlay[global] override DataFlow::Node getABulkExportedNode() { // Assigned to `module.exports` via the factory's `module` parameter exists(AbstractModuleObject m, DataFlow::PropWrite write | diff --git a/javascript/ql/lib/semmle/javascript/AST.qll b/javascript/ql/lib/semmle/javascript/AST.qll index db0a2e153d50..0e6330605ba5 100644 --- a/javascript/ql/lib/semmle/javascript/AST.qll +++ b/javascript/ql/lib/semmle/javascript/AST.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with the AST-based representation of JavaScript programs. */ +overlay[local] +module; import javascript private import internal.StmtContainers @@ -172,6 +174,7 @@ class AstNode extends @ast_node, NodeInStmtContainer { * The TypeScript compiler emits no code for ambient declarations, but they * can affect name resolution and type checking at compile-time. */ + overlay[caller?] pragma[inline] predicate isAmbient() { this.isAmbientInternal() @@ -470,9 +473,12 @@ module AST { */ class ValueNode extends AstNode, @dataflownode { /** Gets type inference results for this element. */ + overlay[global] DataFlow::AnalyzedNode analyze() { result = DataFlow::valueNode(this).analyze() } /** Gets the data flow node associated with this program element. */ + overlay[caller] + pragma[inline] DataFlow::ValueNode flow() { result = DataFlow::valueNode(this) } /** @@ -481,6 +487,7 @@ module AST { * This can be used to map an expression to the class it refers to, or * associate it with a named value coming from an dependency. */ + overlay[global] ExprNameBindingNode getNameBinding() { result = this } /** @@ -490,6 +497,7 @@ module AST { * (according to the type system), or to associate it with a named type coming * from a dependency. */ + overlay[global] TypeNameBindingNode getTypeBinding() { TypeResolution::valueHasType(this, result) } } } diff --git a/javascript/ql/lib/semmle/javascript/Actions.qll b/javascript/ql/lib/semmle/javascript/Actions.qll index a3dd7542ec13..3cde9a914ad3 100644 --- a/javascript/ql/lib/semmle/javascript/Actions.qll +++ b/javascript/ql/lib/semmle/javascript/Actions.qll @@ -4,6 +4,8 @@ * Libraries for modeling GitHub Actions workflow files written in YAML. * See https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Aliases.qll b/javascript/ql/lib/semmle/javascript/Aliases.qll index 021cca85120f..9497e0603361 100644 --- a/javascript/ql/lib/semmle/javascript/Aliases.qll +++ b/javascript/ql/lib/semmle/javascript/Aliases.qll @@ -2,6 +2,8 @@ * Provides aliases for commonly used classes that have different names * in the QL libraries for other languages. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll index 1a96e25b3b9f..d1cd1cb33de5 100644 --- a/javascript/ql/lib/semmle/javascript/ApiGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs.qll @@ -545,7 +545,7 @@ module API { this = Impl::MkClassInstance(result) or this = Impl::MkUse(result) or this = Impl::MkDef(result) or - this = Impl::MkSyntheticCallbackArg(_, _, result) + this = Impl::MkSyntheticCallbackArg(result) } /** @@ -613,12 +613,12 @@ module API { /** A node corresponding to a definition of an API component. */ class Definition extends Node, Impl::TDef { - override string toString() { result = "def " + this.getPath() } + override string toString() { result = "def " + this.getInducingNode().toString() } } /** A node corresponding to the use of an API component. */ class Use extends Node, Impl::TUse { - override string toString() { result = "use " + this.getPath() } + override string toString() { result = "use " + this.getInducingNode().toString() } } /** Gets the root node. */ @@ -676,17 +676,21 @@ module API { * Imports and exports are considered entry points by default, but additional entry points may * be added by extending this class. Typical examples include global variables. */ + overlay[local] abstract class EntryPoint extends string { bindingset[this] EntryPoint() { any() } /** Gets a data-flow node where a value enters the current codebase through this entry-point. */ + overlay[global] DataFlow::SourceNode getASource() { none() } /** Gets a data-flow node where a value leaves the current codebase through this entry-point. */ + overlay[global] DataFlow::Node getASink() { none() } /** Gets an API-node for this entry point. */ + overlay[global] API::Node getANode() { result = root().getASuccessor(Label::entryPoint(this)) } } @@ -731,49 +735,60 @@ module API { */ cached private module Impl { + private predicate hasTypeUse(string moduleName, string exportName) { + any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) + } + + overlay[local] + private predicate hasTypeUseLocal(string moduleName, string exportName) = + forceLocal(hasTypeUse/2)(moduleName, exportName) + + overlay[local] cached newtype TApiNode = MkRoot() or MkModuleDef(string m) { exists(MkModuleExport(m)) } or MkModuleUse(string m) { exists(MkModuleImport(m)) } or - MkModuleExport(string m) { - exists(Module mod | mod = importableModule(m) | - // exclude modules that don't actually export anything - exports(m, _) - or - exports(m, _, _) - or - exists(NodeModule nm | nm = mod | - exists(Ssa::implicitInit([nm.getModuleVariable(), nm.getExportsVariable()])) - ) - ) - } or - MkModuleImport(string m) { - imports(_, m) + MkModuleExport(string m) { isDeclaredPackageName(m) } or + MkModuleImport(string m) { isImportedPackageName(m) } or + MkClassInstance(DataFlow::SourceNode cls) { + cls = any(Function f).flow() or - any(TypeAnnotation n).hasUnderlyingType(m, _) - } or - MkClassInstance(DataFlow::ClassNode cls) { needsDefNode(cls) } or - MkDef(DataFlow::Node nd) { rhs(_, _, nd) } or - MkUse(DataFlow::Node nd) { use(_, _, nd) } or - /** A use of a TypeScript type. */ - MkTypeUse(string moduleName, string exportName) { - any(TypeAnnotation n).hasUnderlyingType(moduleName, exportName) + cls = any(ClassDefinition c).flow() } or - MkSyntheticCallbackArg(DataFlow::Node src, int bound, DataFlow::InvokeNode nd) { - trackUseNode(src, true, bound, "").flowsTo(nd.getCalleeNode()) - } - - private predicate needsDefNode(DataFlow::ClassNode cls) { - hasSemantics(cls) and - ( - cls = trackDefNode(_) + MkDef(DataFlow::Node nd) { + nd = any(DataFlow::PropWrite w).getRhs() or - cls.getAnInstanceReference() = trackDefNode(_) + nd = any(DataFlow::FunctionNode fn).getReturnNode() or - needsDefNode(cls.getADirectSubClass()) - ) - } + nd = any(DataFlow::FunctionNode fn).getAReturn() + or + nd = any(DataFlow::FunctionNode fn).getExceptionalReturn() + or + nd = any(DataFlow::InvokeNode i).getAnArgument() + or + nd = any(DataFlow::InvokeNode i).getASpreadArgument() + or + nd = any(DataFlow::InvokeNode i).getExceptionalReturn() + or + nd = any(ThrowStmt stmt).getExpr().flow() + or + nd = any(DataFlow::CallNode c).getReceiver() + or + nd = DataFlow::valueNode(any(ExportNamedDeclaration decl).getOperand()) + or + nd = DataFlow::valueNode(any(ExportDefaultDeclaration decl).getOperand()) + or + nd = any(ExportNamedDeclaration decl).getOperand().(DeclStmt).getADecl().getInit().flow() + or + nd = any(ExportNamespaceSpecifier spec | exists(spec.getExportedName())).flow() + or + nd = any(MemberDeclaration m).getInit().flow() + } or + MkUse(DataFlow::Node nd) { nd instanceof DataFlow::SourceNode } or + /** A use of a TypeScript type. */ + MkTypeUse(string moduleName, string exportName) { hasTypeUseLocal(moduleName, exportName) } or + MkSyntheticCallbackArg(DataFlow::InvokeNode nd) class TDef = MkModuleDef or TNonModuleDef; @@ -783,698 +798,933 @@ module API { private predicate hasSemantics(DataFlow::Node nd) { not nd.getTopLevel().isExterns() } - /** Holds if `imp` is an import of module `m`. */ - private predicate imports(DataFlow::Node imp, string m) { - imp = DataFlow::moduleImport(m) and - // path must not start with a dot or a slash - m.regexpMatch("[^./].*") and - hasSemantics(imp) + bindingset[nd] + pragma[inline_late] + private predicate hasSemanticsLate(DataFlow::Node nd) { hasSemantics(nd) } + + private signature module StageInputSig { + predicate isAdditionalUseRoot(Node node); + + predicate isAdditionalDefRoot(Node node); + + bindingset[node] + predicate inScope(DataFlow::Node node); } - /** - * Holds if `rhs` is the right-hand side of a definition of a node that should have an - * incoming edge from `base` labeled `lbl` in the API graph. - */ - cached - predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { - hasSemantics(rhs) and - ( - base = MkRoot() and - exists(EntryPoint e | - lbl = Label::entryPoint(e) and - rhs = e.getASink() - ) - or - exists(string m, string prop | - base = MkModuleExport(m) and - lbl = Label::member(prop) and - exports(m, prop, rhs) - ) - or - exists(DataFlow::Node def, DataFlow::SourceNode pred | - rhs(base, def) and pred = trackDefNode(def) - | - // from `x` to a definition of `x.prop` - exists(DataFlow::PropWrite pw | pw = pred.getAPropertyWrite() | - lbl = Label::memberFromRef(pw) and - rhs = pw.getRhs() + private module Stage { + /** + * Holds if `rhs` is the right-hand side of a definition of a node that should have an + * incoming edge from `base` labeled `lbl` in the API graph. + */ + predicate rhs(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { + hasSemantics(rhs) and + ( + base = MkRoot() and + exists(EntryPoint e | + lbl = Label::entryPoint(e) and + rhs = e.getASink() ) or - // special case: from `require('m')` to an export of `prop` in `m` - exists(Import imp, Module m, string prop | - pred = imp.getImportedModuleNodeStrict() and - m = imp.getImportedModule() and + exists(string m, string prop | + base = MkModuleExport(m) and lbl = Label::member(prop) and - rhs = m.getAnExportedValue(prop) + exports(m, prop, rhs) ) or - // In general, turn store steps into member steps for def-nodes - exists(string prop | - PreCallGraphStep::storeStep(rhs, pred, prop) and - lbl = Label::member(prop) and - not DataFlow::PseudoProperties::isPseudoProperty(prop) + exists(DataFlow::Node def, DataFlow::SourceNode pred | + rhs(base, def) and pred = trackDefNode(def) + | + // from `x` to a definition of `x.prop` + exists(DataFlow::PropWrite pw | pw = pred.getAPropertyWrite() | + lbl = Label::memberFromRef(pw) and + rhs = pw.getRhs() + ) + or + // special case: from `require('m')` to an export of `prop` in `m` + exists(Import imp, Module m, string prop | + pred = imp.getImportedModuleNodeStrict() and + m = imp.getImportedModule() and + lbl = Label::member(prop) and + rhs = m.getAnExportedValue(prop) + ) + or + // In general, turn store steps into member steps for def-nodes + exists(string prop | + PreCallGraphStep::storeStep(rhs, pred, prop) and + lbl = Label::member(prop) and + not DataFlow::PseudoProperties::isPseudoProperty(prop) + ) + or + exists(DataFlow::ContentSet contents | + SummaryTypeTracker::basicStoreStep(rhs, pred.getALocalUse(), contents) and + lbl = Label::content(contents.getAStoreContent()) + ) + or + exists(DataFlow::FunctionNode fn | + fn = pred and + lbl = Label::return() + | + if fn.getFunction().isAsync() then rhs = fn.getReturnNode() else rhs = fn.getAReturn() + ) + or + lbl = Label::promised() and + SharedTypeTrackingStep::storeStep(rhs, pred, Promises::valueProp()) + or + lbl = Label::promisedError() and + SharedTypeTrackingStep::storeStep(rhs, pred, Promises::errorProp()) + or + // The return-value of a getter G counts as a definition of property G + // (Ordinary methods and properties are handled as PropWrite nodes) + exists(string name | lbl = Label::member(name) | + rhs = pred.(DataFlow::ObjectLiteralNode).getPropertyGetter(name).getAReturn() + or + rhs = + pred.(DataFlow::ClassNode) + .getStaticMember(name, DataFlow::MemberKind::getter()) + .getAReturn() + ) + or + // Handle rest parameters escaping into external code. For example: + // + // function foo(...rest) { + // externalFunc(rest); + // } + // + // Here, 'rest' reaches a def-node at the call to externalFunc, so we need to ensure + // the arguments passed to 'foo' are stored in the 'rest' array. + exists(Function fun, DataFlow::InvokeNode invoke, int argIndex, Parameter rest | + fun.getRestParameter() = rest and + rest.flow() = pred and + invoke.getACallee() = fun and + invoke.getArgument(argIndex) = rhs and + argIndex >= rest.getIndex() and + lbl = Label::member((argIndex - rest.getIndex()).toString()) + ) ) or - exists(DataFlow::ContentSet contents | - SummaryTypeTracker::basicStoreStep(rhs, pred.getALocalUse(), contents) and - lbl = Label::content(contents.getAStoreContent()) + exists(DataFlow::ClassNode cls, string name | + base = MkClassInstance(cls) and + lbl = Label::member(name) + | + rhs = cls.getInstanceMethod(name) + or + rhs = cls.getInstanceMember(name, DataFlow::MemberKind::getter()).getAReturn() ) or - exists(DataFlow::FunctionNode fn | - fn = pred and - lbl = Label::return() + exists(DataFlow::FunctionNode f | + f.getFunction().isAsync() and + base = MkDef(f.getReturnNode()) | - if fn.getFunction().isAsync() then rhs = fn.getReturnNode() else rhs = fn.getAReturn() + lbl = Label::promised() and + rhs = f.getAReturn() + or + lbl = Label::promisedError() and + rhs = f.getExceptionalReturn() ) or - lbl = Label::promised() and - SharedTypeTrackingStep::storeStep(rhs, pred, Promises::valueProp()) - or - lbl = Label::promisedError() and - SharedTypeTrackingStep::storeStep(rhs, pred, Promises::errorProp()) - or - // The return-value of a getter G counts as a definition of property G - // (Ordinary methods and properties are handled as PropWrite nodes) - exists(string name | lbl = Label::member(name) | - rhs = pred.(DataFlow::ObjectLiteralNode).getPropertyGetter(name).getAReturn() + exists(int i | argumentPassing(base, i, rhs) | + lbl = Label::parameter(i) or - rhs = - pred.(DataFlow::ClassNode) - .getStaticMember(name, DataFlow::MemberKind::getter()) - .getAReturn() + i = -1 and lbl = Label::receiver() ) or - // Handle rest parameters escaping into external code. For example: - // - // function foo(...rest) { - // externalFunc(rest); - // } - // - // Here, 'rest' reaches a def-node at the call to externalFunc, so we need to ensure - // the arguments passed to 'foo' are stored in the 'rest' array. - exists(Function fun, DataFlow::InvokeNode invoke, int argIndex, Parameter rest | - fun.getRestParameter() = rest and - rest.flow() = pred and - invoke.getACallee() = fun and - invoke.getArgument(argIndex) = rhs and - argIndex >= rest.getIndex() and - lbl = Label::member((argIndex - rest.getIndex()).toString()) + exists(int i | + spreadArgumentPassing(base, i, rhs) and + lbl = Label::spreadArgument(i) ) - ) - or - exists(DataFlow::ClassNode cls, string name | - base = MkClassInstance(cls) and - lbl = Label::member(name) - | - rhs = cls.getInstanceMethod(name) or - rhs = cls.getInstanceMember(name, DataFlow::MemberKind::getter()).getAReturn() + exists(DataFlow::SourceNode src, DataFlow::PropWrite pw | + use(base, src) and pw = trackUseNode(src).getAPropertyWrite() and rhs = pw.getRhs() + | + lbl = Label::memberFromRef(pw) + ) ) or - exists(DataFlow::FunctionNode f | - f.getFunction().isAsync() and - base = MkDef(f.getReturnNode()) - | - lbl = Label::promised() and - rhs = f.getAReturn() - or - lbl = Label::promisedError() and - rhs = f.getExceptionalReturn() - ) + decoratorDualEdge(base, lbl, rhs) or - exists(int i | argumentPassing(base, i, rhs) | - lbl = Label::parameter(i) - or - i = -1 and lbl = Label::receiver() - ) + decoratorRhsEdge(base, lbl, rhs) or - exists(int i | - spreadArgumentPassing(base, i, rhs) and - lbl = Label::spreadArgument(i) + exists(DataFlow::PropWrite write | + decoratorPropEdge(base, lbl, write) and + rhs = write.getRhs() ) - or - exists(DataFlow::SourceNode src, DataFlow::PropWrite pw | - use(base, src) and pw = trackUseNode(src).getAPropertyWrite() and rhs = pw.getRhs() - | - lbl = Label::memberFromRef(pw) - ) - ) - or - decoratorDualEdge(base, lbl, rhs) - or - decoratorRhsEdge(base, lbl, rhs) - or - exists(DataFlow::PropWrite write | - decoratorPropEdge(base, lbl, write) and - rhs = write.getRhs() - ) - } + } - /** - * Holds if `arg` is passed as the `i`th argument to a use of `base`, either by means of a - * full invocation, or in a partial function application. - * - * The receiver is considered to be argument -1. - */ - private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) { - exists(DataFlow::Node use, DataFlow::SourceNode pred, int bound | - use(base, use) and pred = trackUseNode(use, _, bound, "") - | - arg = pred.getAnInvocation().getArgument(i - bound) - or - arg = pred.getACall().getReceiver() and - bound = 0 and - i = -1 - or - exists(DataFlow::PartialInvokeNode pin, DataFlow::Node callback | pred.flowsTo(callback) | - pin.isPartialArgument(callback, arg, i - bound) + /** + * Holds if `arg` is passed as the `i`th argument to a use of `base`, either by means of a + * full invocation, or in a partial function application. + * + * The receiver is considered to be argument -1. + */ + private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) { + exists(DataFlow::Node use, DataFlow::SourceNode pred, int bound | + use(base, use) and pred = trackUseNode(use, _, bound, "") + | + arg = pred.getAnInvocation().getArgument(i - bound) or - arg = pin.getBoundReceiver(callback) and + arg = pred.getACall().getReceiver() and bound = 0 and i = -1 + or + exists(DataFlow::PartialInvokeNode pin, DataFlow::Node callback | pred.flowsTo(callback) | + pin.isPartialArgument(callback, arg, i - bound) + or + arg = pin.getBoundReceiver(callback) and + bound = 0 and + i = -1 + ) ) - ) - } + } - pragma[nomagic] - private int firstSpreadIndex(InvokeExpr expr) { - result = min(int i | expr.getArgument(i) instanceof SpreadElement) - } + pragma[nomagic] + private int firstSpreadIndex(InvokeExpr expr) { + result = min(int i | expr.getArgument(i) instanceof SpreadElement) + } - pragma[nomagic] - private InvokeExpr getAnInvocationWithSpread(DataFlow::SourceNode node, int i) { - result = node.getAnInvocation().asExpr() and - i = firstSpreadIndex(result) - } + pragma[nomagic] + private InvokeExpr getAnInvocationWithSpread(DataFlow::SourceNode node, int i) { + result = node.getAnInvocation().asExpr() and + i = firstSpreadIndex(result) + } - private predicate spreadArgumentPassing(TApiNode base, int i, DataFlow::Node spreadArray) { - exists( - DataFlow::Node use, DataFlow::SourceNode pred, int bound, InvokeExpr invoke, int spreadPos - | - use(base, use) and - pred = trackUseNode(use, _, bound, "") and - invoke = getAnInvocationWithSpread(pred, spreadPos) and - spreadArray = invoke.getArgument(spreadPos).(SpreadElement).getOperand().flow() and - i = bound + spreadPos - ) - } + private predicate spreadArgumentPassing(TApiNode base, int i, DataFlow::Node spreadArray) { + exists( + DataFlow::Node use, DataFlow::SourceNode pred, int bound, InvokeExpr invoke, int spreadPos + | + use(base, use) and + pred = trackUseNode(use, _, bound, "") and + invoke = getAnInvocationWithSpread(pred, spreadPos) and + spreadArray = invoke.getArgument(spreadPos).(SpreadElement).getOperand().flow() and + i = bound + spreadPos + ) + } - /** - * Holds if `rhs` is the right-hand side of a definition of node `nd`. - */ - cached - predicate rhs(TApiNode nd, DataFlow::Node rhs) { - exists(string m | nd = MkModuleExport(m) | exports(m, rhs)) - or - nd = MkDef(rhs) - } + /** + * Holds if `rhs` is the right-hand side of a definition of node `nd`. + */ + predicate rhs(TApiNode nd, DataFlow::Node rhs) { + (S::inScope(rhs) or S::isAdditionalDefRoot(nd)) and + exists(string m | nd = MkModuleExport(m) | exports(m, rhs)) + or + rhs(_, _, rhs) and + S::inScope(rhs) and + nd = MkDef(rhs) + } - /** - * Holds if `ref` is a read of a property described by `lbl` on `pred`, and - * `propDesc` is compatible with that property, meaning it is either the - * name of the property itself or the empty string. - */ - pragma[noinline] - private predicate propertyRead( - DataFlow::SourceNode pred, string propDesc, Label::ApiLabel lbl, DataFlow::Node ref - ) { - ref = pred.getAPropertyRead() and - lbl = Label::memberFromRef(ref) and - ( - lbl = Label::member(propDesc) + /** + * Holds if `ref` is a read of a property described by `lbl` on `pred`, and + * `propDesc` is compatible with that property, meaning it is either the + * name of the property itself or the empty string. + */ + pragma[noinline] + private predicate propertyRead( + DataFlow::SourceNode pred, string propDesc, Label::ApiLabel lbl, DataFlow::Node ref + ) { + ref = pred.getAPropertyRead() and + lbl = Label::memberFromRef(ref) and + ( + lbl = Label::member(propDesc) + or + propDesc = "" + ) or - propDesc = "" - ) - or - SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::valueProp()) and - lbl = Label::promised() and - (propDesc = Promises::valueProp() or propDesc = "") - or - SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::errorProp()) and - lbl = Label::promisedError() and - (propDesc = Promises::errorProp() or propDesc = "") - } + SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::valueProp()) and + lbl = Label::promised() and + (propDesc = Promises::valueProp() or propDesc = "") + or + SharedTypeTrackingStep::loadStep(pred.getALocalUse(), ref, Promises::errorProp()) and + lbl = Label::promisedError() and + (propDesc = Promises::errorProp() or propDesc = "") + } - pragma[nomagic] - private DataFlow::ClassNode getALocalSubclass(DataFlow::SourceNode node) { - result.getASuperClassNode().getALocalSource() = node - } + pragma[nomagic] + private DataFlow::ClassNode getALocalSubclass(DataFlow::SourceNode node) { + result.getASuperClassNode().getALocalSource() = node + } - bindingset[node] - pragma[inline_late] - private DataFlow::ClassNode getALocalSubclassFwd(DataFlow::SourceNode node) { - result = getALocalSubclass(node) - } + bindingset[node] + pragma[inline_late] + private DataFlow::ClassNode getALocalSubclassFwd(DataFlow::SourceNode node) { + result = getALocalSubclass(node) + } - /** - * Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled - * `lbl` in the API graph. - */ - cached - predicate use(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { - hasSemantics(ref) and - ( - base = MkRoot() and - exists(EntryPoint e | - lbl = Label::entryPoint(e) and - ref = e.getASource() + /** + * Holds if `ref` is a use of a node that should have an incoming edge from `base` labeled + * `lbl` in the API graph. + */ + predicate use(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { + hasSemantics(ref) and + ( + base = MkRoot() and + exists(EntryPoint e | + lbl = Label::entryPoint(e) and + ref = e.getASource() and + S::inScope(ref) + ) + or + // property reads + exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc | + use(base, src) and + pred = trackUseNode(src, false, 0, propDesc) and + propertyRead(pred, propDesc, lbl, ref) and + // `module.exports` is special: it is a use of a def-node, not a use-node, + // so we want to exclude it here + (base instanceof TNonModuleDef or base instanceof TUse) + ) + or + exists(DataFlow::SourceNode src, DataFlow::SourceNode pred | + use(base, src) and pred = trackUseNode(src) + | + lbl = Label::instance() and + ref = pred.getAnInstantiation() + or + lbl = Label::return() and + ref = pred.getAnInvocation() + or + lbl = Label::forwardingFunction() and + DataFlow::functionForwardingStep(pred.getALocalUse(), ref) + or + exists(DataFlow::ClassNode cls | + lbl = Label::instance() and + cls = getALocalSubclassFwd(pred).getADirectSubClass*() + | + ref = cls.getAReceiverNode() + or + ref = cls.getAClassReference().getAnInstantiation() + ) + or + exists(string prop | + PreCallGraphStep::loadStep(pred.getALocalUse(), ref, prop) and + lbl = Label::member(prop) and + // avoid generating member edges like "$arrayElement$" + not DataFlow::PseudoProperties::isPseudoProperty(prop) + ) + or + exists(DataFlow::ContentSet contents | + SummaryTypeTracker::basicLoadStep(pred.getALocalUse(), ref, contents) and + lbl = Label::content(contents.getAStoreContent()) + ) + ) + or + exists(DataFlow::Node def, DataFlow::FunctionNode fn | + rhs(base, def) and fn = trackDefNode(def) + | + exists(int i | + lbl = Label::parameter(i) and + ref = fn.getParameter(i) + ) + or + lbl = Label::receiver() and + ref = fn.getReceiver() + ) + or + exists(DataFlow::Node def, DataFlow::ClassNode cls, int i | + rhs(base, def) and cls = trackDefNode(def) + | + lbl = Label::parameter(i) and + ref = cls.getConstructor().getParameter(i) + ) + or + exists(string moduleName, string exportName | + base = MkTypeUse(moduleName, exportName) and + lbl = Label::instance() and + ref.(DataFlow::SourceNode).hasUnderlyingType(moduleName, exportName) + ) + or + exists(DataFlow::InvokeNode call | + base = MkSyntheticCallbackArg(call) and + lbl = Label::parameter(1) and + ref = awaited(call) + ) + or + decoratorDualEdge(base, lbl, ref) + or + decoratorUseEdge(base, lbl, ref) + or + // for fields and accessors, mark the reads as use-nodes + decoratorPropEdge(base, lbl, ref.(DataFlow::PropRead)) + ) + } + + /** Holds if `base` is a use-node that flows to the decorator expression of the given decorator. */ + pragma[nomagic] + private predicate useNodeFlowsToDecorator(TApiNode base, Decorator decorator) { + exists(DataFlow::SourceNode decoratorSrc | + use(base, decoratorSrc) and + trackUseNode(decoratorSrc).flowsToExpr(decorator.getExpression()) + ) + } + + /** + * Holds if `ref` corresponds to both a use and def-node that should have an incoming edge from `base` labelled `lbl`. + * + * This happens because the decorated value escapes into the decorator function, and is then replaced + * by the function's return value. In the JS analysis we generally assume decorators return their input, + * but library models may want to find the return value. + */ + private predicate decoratorDualEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { + exists(ClassDefinition cls | + useNodeFlowsToDecorator(base, cls.getADecorator()) and + lbl = Label::decoratedClass() and + ref = DataFlow::valueNode(cls) ) or - // property reads - exists(DataFlow::SourceNode src, DataFlow::SourceNode pred, string propDesc | - use(base, src) and - pred = trackUseNode(src, false, 0, propDesc) and - propertyRead(pred, propDesc, lbl, ref) and - // `module.exports` is special: it is a use of a def-node, not a use-node, - // so we want to exclude it here - (base instanceof TNonModuleDef or base instanceof TUse) + exists(MethodDefinition method | + useNodeFlowsToDecorator(base, method.getADecorator()) and + not method instanceof AccessorMethodDefinition and + lbl = Label::decoratedMember() and + ref = DataFlow::valueNode(method.getBody()) + ) + } + + /** Holds if `ref` is a use that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ + private predicate decoratorUseEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { + exists(SetterMethodDefinition accessor | + useNodeFlowsToDecorator(base, + [accessor.getADecorator(), accessor.getCorrespondingGetter().getADecorator()]) and + lbl = Label::decoratedMember() and + ref = DataFlow::parameterNode(accessor.getBody().getParameter(0)) ) or - exists(DataFlow::SourceNode src, DataFlow::SourceNode pred | - use(base, src) and pred = trackUseNode(src) + exists(Parameter param | + useNodeFlowsToDecorator(base, param.getADecorator()) and + lbl = Label::decoratedParameter() and + ref = DataFlow::parameterNode(param) + ) + } + + /** Holds if `rhs` is a def node that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ + private predicate decoratorRhsEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { + exists(GetterMethodDefinition accessor | + useNodeFlowsToDecorator(base, + [accessor.getADecorator(), accessor.getCorrespondingSetter().getADecorator()]) and + lbl = Label::decoratedMember() and + rhs = DataFlow::valueNode(accessor.getBody().getAReturnedExpr()) + ) + } + + /** + * Holds if `ref` is a reference to a field/accessor that should have en incoming edge from base labelled `lbl`. + * + * Since fields do not have their own data-flow nodes, we generate a node for each read or write. + * For property writes, the right-hand side becomes a def-node and property reads become use-nodes. + * + * For accessors this predicate computes each use of the accessor. + * The return value inside the accessor is computed by the `decoratorRhsEdge` predicate. + */ + private predicate decoratorPropEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::PropRef ref) { + exists(MemberDefinition fieldLike, DataFlow::ClassNode cls | + fieldLike instanceof FieldDefinition + or + fieldLike instanceof AccessorMethodDefinition | - lbl = Label::instance() and - ref = pred.getAnInstantiation() + useNodeFlowsToDecorator(base, fieldLike.getADecorator()) and + lbl = Label::decoratedMember() and + cls = fieldLike.getDeclaringClass().flow() and + ( + fieldLike.isStatic() and + ref = cls.getAClassReference().getAPropertyReference(fieldLike.getName()) + or + not fieldLike.isStatic() and + ref = cls.getAnInstanceReference().getAPropertyReference(fieldLike.getName()) + ) + ) + } + + private predicate needsDefNode(DataFlow::ClassNode cls) { + hasSemantics(cls) and + ( + cls = trackDefNode(_) or - lbl = Label::return() and - ref = pred.getAnInvocation() + cls.getAnInstanceReference() = trackDefNode(_) or - lbl = Label::forwardingFunction() and - DataFlow::functionForwardingStep(pred.getALocalUse(), ref) + needsDefNode(cls.getADirectSubClass()) or - exists(DataFlow::ClassNode cls | - lbl = Label::instance() and - cls = getALocalSubclassFwd(pred).getADirectSubClass*() - | - ref = cls.getAReceiverNode() - or - ref = cls.getAClassReference().getAnInstantiation() + S::isAdditionalDefRoot(MkClassInstance(cls)) + or + S::isAdditionalUseRoot(MkClassInstance(cls)) // These are also tracked as use-nodes + ) + } + + /** + * Holds if `ref` is a use of node `nd`. + */ + predicate use(TApiNode nd, DataFlow::Node ref) { + (S::inScope(ref) or S::isAdditionalUseRoot(nd)) and + ( + exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) | + ref = DataFlow::moduleVarNode(mod) ) or - exists(string prop | - PreCallGraphStep::loadStep(pred.getALocalUse(), ref, prop) and - lbl = Label::member(prop) and - // avoid generating member edges like "$arrayElement$" - not DataFlow::PseudoProperties::isPseudoProperty(prop) + exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) | + ref = DataFlow::exportsVarNode(mod) + or + exists(DataFlow::Node base | use(MkModuleDef(m), base) | + ref = trackUseNode(base).getAPropertyRead("exports") + ) ) or - exists(DataFlow::ContentSet contents | - SummaryTypeTracker::basicLoadStep(pred.getALocalUse(), ref, contents) and - lbl = Label::content(contents.getAStoreContent()) + exists(string m | + nd = MkModuleImport(m) and + ref = DataFlow::moduleImport(m) ) ) or - exists(DataFlow::Node def, DataFlow::FunctionNode fn | - rhs(base, def) and fn = trackDefNode(def) - | - exists(int i | - lbl = Label::parameter(i) and - ref = fn.getParameter(i) - ) + exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) and needsDefNode(cls) | + ref = cls.getAReceiverNode() or - lbl = Label::receiver() and - ref = fn.getReceiver() + ref = cls.(DataFlow::ClassNode).getAPrototypeReference() ) or - exists(DataFlow::Node def, DataFlow::ClassNode cls, int i | - rhs(base, def) and cls = trackDefNode(def) - | - lbl = Label::parameter(i) and - ref = cls.getConstructor().getParameter(i) + use(_, _, ref) and + S::inScope(ref) and + nd = MkUse(ref) + or + S::isAdditionalUseRoot(nd) and + nd = mkUseLate(ref) + } + + bindingset[node] + pragma[inline_late] + private TApiNode mkUseLate(DataFlow::Node node) { result = MkUse(node) } + + private import semmle.javascript.dataflow.TypeTracking + + /** + * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows. + * + * The flow from `nd` to that node may be inter-procedural, and is further described by three + * flags: + * + * - `promisified`: if true `true`, the flow goes through a promisification; + * - `boundArgs`: for function values, tracks how many arguments have been bound throughout + * the flow. To ensure termination, we somewhat arbitrarily constrain the number of bound + * arguments to be at most ten. + * - `prop`: if non-empty, the flow is only guaranteed to preserve the value of this property, + * and not necessarily the entire object. + */ + private DataFlow::SourceNode trackUseNode( + DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop, + DataFlow::TypeTracker t + ) { + t.start() and + use(_, nd) and + result = nd and + promisified = false and + boundArgs = 0 and + prop = "" + or + exists(Promisify::PromisifyCall promisify | + trackUseNode(nd, false, boundArgs, prop, t.continue()).flowsTo(promisify.getArgument(0)) and + promisified = true and + prop = "" and + result = promisify ) or - exists(string moduleName, string exportName | - base = MkTypeUse(moduleName, exportName) and - lbl = Label::instance() and - ref.(DataFlow::SourceNode).hasUnderlyingType(moduleName, exportName) + exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | + trackUseNode(nd, promisified, predBoundArgs, prop, t.continue()).flowsTo(pred) and + prop = "" and + result = pin.getBoundFunction(pred, boundArgs - predBoundArgs) and + boundArgs in [0 .. 10] ) or - exists(DataFlow::InvokeNode call | - base = MkSyntheticCallbackArg(_, _, call) and - lbl = Label::parameter(1) and - ref = awaited(call) + exists(DataFlow::SourceNode mid | + mid = trackUseNode(nd, promisified, boundArgs, prop, t) and + AdditionalUseStep::step(pragma[only_bind_out](mid), result) ) or - // Handle promisified object member access: promisify(obj).member should be treated as obj.member (promisified) - exists( - Promisify::PromisifyAllCall promisifiedObj, DataFlow::SourceNode originalObj, - string member + exists(DataFlow::Node pred, string preprop | + trackUseNode(nd, promisified, boundArgs, preprop, t.continue()).flowsTo(pred) and + promisified = false and + boundArgs = 0 and + SharedTypeTrackingStep::loadStoreStep(pred, result, prop) | - originalObj.flowsTo(promisifiedObj.getArgument(0)) and - use(base, originalObj) and - lbl = Label::member(member) and - ref = promisifiedObj.getAPropertyRead(member) + prop = preprop + or + preprop = "" ) or - decoratorDualEdge(base, lbl, ref) + t = useStep(nd, promisified, boundArgs, prop, result) + } + + /** + * Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially + * inter-procedural steps to some intermediate node, and then from that intermediate node to + * `res` in one step. The entire flow is described by the resulting `TypeTracker`. + * + * This predicate exists solely to enforce a better join order in `trackUseNode` above. + */ + pragma[noopt] + private DataFlow::TypeTracker useStep( + DataFlow::Node nd, boolean promisified, int boundArgs, string prop, DataFlow::Node res + ) { + exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev | + prev = trackUseNode(nd, promisified, boundArgs, prop, t) and + StepSummary::step(prev, res, summary) and + result = t.append(summary) and + // Block argument-passing into 'this' when it determines the call target + not summary = CallReceiverStep() + ) + } + + private DataFlow::SourceNode trackUseNode( + DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop + ) { + result = trackUseNode(nd, promisified, boundArgs, prop, DataFlow::TypeTracker::end()) + } + + /** + * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node. + */ + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { + result = trackUseNode(nd, false, 0, "") + } + + /** + * Gets a node whose forward tracking reaches `nd` in some state (e.g. possibly inside a content at this point). + */ + DataFlow::SourceNode trackUseNodeAnyState(DataFlow::SourceNode nd) { + result = trackUseNode(nd, _, _, _, _) + } + + private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { + t.start() and + rhs(_, nd) and + result = nd.getALocalSource() + or + // additional backwards step from `require('m')` to `exports` or `module.exports` in m + exists(Import imp | imp.getImportedModuleNodeStrict() = trackDefNode(nd, t.continue()) | + result = DataFlow::exportsVarNode(imp.getImportedModule()) + or + result = DataFlow::moduleVarNode(imp.getImportedModule()).getAPropertyRead("exports") + ) or - decoratorUseEdge(base, lbl, ref) + exists(ObjectExpr obj | + obj = trackDefNode(nd, t.continue()).asExpr() and + result = + obj.getAProperty() + .(SpreadProperty) + .getInit() + .(SpreadElement) + .getOperand() + .flow() + .getALocalSource() + ) or - // for fields and accessors, mark the reads as use-nodes - decoratorPropEdge(base, lbl, ref.(DataFlow::PropRead)) - ) - } + t = defStep(nd, result) + } - /** Holds if `base` is a use-node that flows to the decorator expression of the given decorator. */ - pragma[nomagic] - private predicate useNodeFlowsToDecorator(TApiNode base, Decorator decorator) { - exists(DataFlow::SourceNode decoratorSrc | - use(base, decoratorSrc) and - trackUseNode(decoratorSrc).flowsToExpr(decorator.getExpression()) - ) - } + /** + * Holds if `nd`, which is a def of an API-graph node, can be reached in zero or more potentially + * inter-procedural steps from some intermediate node, and `prev` flows into that intermediate node + * in one step. The entire flow is described by the resulting `TypeTracker`. + * + * This predicate exists solely to enforce a better join order in `trackDefNode` above. + */ + pragma[noopt] + private DataFlow::TypeBackTracker defStep(DataFlow::Node nd, DataFlow::SourceNode prev) { + exists(DataFlow::TypeBackTracker t, StepSummary summary, DataFlow::Node next | + next = trackDefNode(nd, t) and + StepSummary::step(prev, next, summary) and + result = t.prepend(summary) and + // Block argument-passing into 'this' when it determines the call target + not summary = CallReceiverStep() + ) + } - /** - * Holds if `ref` corresponds to both a use and def-node that should have an incoming edge from `base` labelled `lbl`. - * - * This happens because the decorated value escapes into the decorator function, and is then replaced - * by the function's return value. In the JS analysis we generally assume decorators return their input, - * but library models may want to find the return value. - */ - private predicate decoratorDualEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { - exists(ClassDefinition cls | - useNodeFlowsToDecorator(base, cls.getADecorator()) and - lbl = Label::decoratedClass() and - ref = DataFlow::valueNode(cls) - ) - or - exists(MethodDefinition method | - useNodeFlowsToDecorator(base, method.getADecorator()) and - not method instanceof AccessorMethodDefinition and - lbl = Label::decoratedMember() and - ref = DataFlow::valueNode(method.getBody()) - ) - } + /** + * Gets a node that inter-procedurally flows into `nd`, which is a definition of some node. + */ + DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { + result = trackDefNode(nd, DataFlow::TypeBackTracker::end()) + } - /** Holds if `ref` is a use that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ - private predicate decoratorUseEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node ref) { - exists(SetterMethodDefinition accessor | - useNodeFlowsToDecorator(base, - [accessor.getADecorator(), accessor.getCorrespondingGetter().getADecorator()]) and - lbl = Label::decoratedMember() and - ref = DataFlow::parameterNode(accessor.getBody().getParameter(0)) - ) - or - exists(Parameter param | - useNodeFlowsToDecorator(base, param.getADecorator()) and - lbl = Label::decoratedParameter() and - ref = DataFlow::parameterNode(param) - ) - } + /** + * Gets a node reached by the backwards tracking of `nd` in some state (e.g. possibly inside a content at this point). + */ + DataFlow::SourceNode trackDefNodeAnyState(DataFlow::Node nd) { result = trackDefNode(nd, _) } - /** Holds if `rhs` is a def node that should have an incoming edge from `base` labelled `lbl`, induced by a decorator. */ - private predicate decoratorRhsEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::Node rhs) { - exists(GetterMethodDefinition accessor | - useNodeFlowsToDecorator(base, - [accessor.getADecorator(), accessor.getCorrespondingSetter().getADecorator()]) and - lbl = Label::decoratedMember() and - rhs = DataFlow::valueNode(accessor.getBody().getAReturnedExpr()) - ) - } + private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { + t.startInPromise() and + trackUseNode(_, true, _, "").flowsTo(call.getCalleeNode()) and + result = call + or + exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) + } - /** - * Holds if `ref` is a reference to a field/accessor that should have en incoming edge from base labelled `lbl`. - * - * Since fields do not have their own data-flow nodes, we generate a node for each read or write. - * For property writes, the right-hand side becomes a def-node and property reads become use-nodes. - * - * For accessors this predicate computes each use of the accessor. - * The return value inside the accessor is computed by the `decoratorRhsEdge` predicate. - */ - private predicate decoratorPropEdge(TApiNode base, Label::ApiLabel lbl, DataFlow::PropRef ref) { - exists(MemberDefinition fieldLike, DataFlow::ClassNode cls | - fieldLike instanceof FieldDefinition + /** + * Gets a node holding the resolved value of promise `call`. + */ + private DataFlow::Node awaited(DataFlow::InvokeNode call) { + result = awaited(call, DataFlow::TypeTracker::end()) + } + + /** + * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`. + */ + predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { + Stages::ApiStage::ref() and + exists(string m | + pred = MkRoot() and + lbl = Label::moduleLabel(m) + | + succ = MkModuleDef(m) + or + succ = MkModuleUse(m) + ) or - fieldLike instanceof AccessorMethodDefinition - | - useNodeFlowsToDecorator(base, fieldLike.getADecorator()) and - lbl = Label::decoratedMember() and - cls = fieldLike.getDeclaringClass().flow() and - ( - fieldLike.isStatic() and - ref = cls.getAClassReference().getAPropertyReference(fieldLike.getName()) + exists(string m | + pred = MkModuleDef(m) and + lbl = Label::member("exports") and + succ = MkModuleExport(m) or - not fieldLike.isStatic() and - ref = cls.getAnInstanceReference().getAPropertyReference(fieldLike.getName()) + pred = MkModuleUse(m) and + lbl = Label::member("exports") and + succ = MkModuleImport(m) ) - ) - } - - /** - * Holds if `ref` is a use of node `nd`. - */ - cached - predicate use(TApiNode nd, DataFlow::Node ref) { - exists(string m, Module mod | nd = MkModuleDef(m) and mod = importableModule(m) | - ref = DataFlow::moduleVarNode(mod) - ) - or - exists(string m, Module mod | nd = MkModuleExport(m) and mod = importableModule(m) | - ref = DataFlow::exportsVarNode(mod) or - exists(DataFlow::Node base | use(MkModuleDef(m), base) | - ref = trackUseNode(base).getAPropertyRead("exports") + exists(DataFlow::SourceNode ref | + use(pred, lbl, ref) and + succ = MkUse(ref) ) - ) - or - exists(string m | - nd = MkModuleImport(m) and - ref = DataFlow::moduleImport(m) - ) - or - exists(DataFlow::ClassNode cls | nd = MkClassInstance(cls) | - ref = cls.getAReceiverNode() or - ref = cls.(DataFlow::ClassNode).getAPrototypeReference() - ) - or - nd = MkUse(ref) + exists(DataFlow::Node rhs | rhs(pred, lbl, rhs) | + succ = MkDef(rhs) + or + exists(DataFlow::ClassNode cls | + cls.getAnInstanceReference().flowsTo(rhs) and + succ = MkClassInstance(cls) + ) + ) + or + exists(DataFlow::Node def | + rhs(pred, def) and + lbl = Label::instance() and + succ = MkClassInstance(trackDefNode(def)) + ) + or + exists(string moduleName, string exportName | + pred = MkModuleImport(moduleName) and + lbl = Label::member(exportName) and + succ = MkTypeUse(moduleName, exportName) + ) + or + exists(DataFlow::Node nd, DataFlow::FunctionNode f | + f.getFunction().isAsync() and + pred = MkDef(nd) and + f = trackDefNode(nd) and + lbl = Label::return() and + succ = MkDef(f.getReturnNode()) + ) + or + exists(int bound, DataFlow::InvokeNode call | + lbl = Label::parameter(bound + call.getNumArgument()) and + call = getAPromisifiedInvocation(pred, bound, succ) + ) + } + + /** + * Gets a call to a promisified function represented by `callee` where + * `bound` arguments have been bound. + */ + DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { + exists(DataFlow::SourceNode src | + use(callee, src) and + trackUseNode(src, true, bound, "").flowsTo(result.getCalleeNode()) and + succ = Impl::MkSyntheticCallbackArg(result) + ) + } } - private import semmle.javascript.dataflow.TypeTracking + private module Stage1Input implements StageInputSig { + pragma[inline] + predicate isAdditionalUseRoot(Node node) { none() } - /** - * Gets a data-flow node to which `nd`, which is a use of an API-graph node, flows. - * - * The flow from `nd` to that node may be inter-procedural, and is further described by three - * flags: - * - * - `promisified`: if true `true`, the flow goes through a promisification; - * - `boundArgs`: for function values, tracks how many arguments have been bound throughout - * the flow. To ensure termination, we somewhat arbitrarily constrain the number of bound - * arguments to be at most ten. - * - `prop`: if non-empty, the flow is only guaranteed to preserve the value of this property, - * and not necessarily the entire object. - */ - private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop, - DataFlow::TypeTracker t - ) { - t.start() and - use(_, nd) and - result = nd and - promisified = false and - boundArgs = 0 and - prop = "" - or - exists(Promisify::PromisifyCall promisify | - trackUseNode(nd, false, boundArgs, prop, t.continue()).flowsTo(promisify.getArgument(0)) and - promisified = true and - prop = "" and - result = promisify - ) - or - exists(DataFlow::PartialInvokeNode pin, DataFlow::Node pred, int predBoundArgs | - trackUseNode(nd, promisified, predBoundArgs, prop, t.continue()).flowsTo(pred) and - prop = "" and - result = pin.getBoundFunction(pred, boundArgs - predBoundArgs) and - boundArgs in [0 .. 10] - ) - or - exists(DataFlow::SourceNode mid | - mid = trackUseNode(nd, promisified, boundArgs, prop, t) and - AdditionalUseStep::step(pragma[only_bind_out](mid), result) - ) - or - exists(DataFlow::Node pred, string preprop | - trackUseNode(nd, promisified, boundArgs, preprop, t.continue()).flowsTo(pred) and - promisified = false and - boundArgs = 0 and - SharedTypeTrackingStep::loadStoreStep(pred, result, prop) - | - prop = preprop - or - preprop = "" - ) - or - t = useStep(nd, promisified, boundArgs, prop, result) - } + pragma[inline] + predicate isAdditionalDefRoot(Node node) { none() } - /** - * Holds if `nd`, which is a use of an API-graph node, flows in zero or more potentially - * inter-procedural steps to some intermediate node, and then from that intermediate node to - * `res` in one step. The entire flow is described by the resulting `TypeTracker`. - * - * This predicate exists solely to enforce a better join order in `trackUseNode` above. - */ - pragma[noopt] - private DataFlow::TypeTracker useStep( - DataFlow::Node nd, boolean promisified, int boundArgs, string prop, DataFlow::Node res - ) { - exists(DataFlow::TypeTracker t, StepSummary summary, DataFlow::SourceNode prev | - prev = trackUseNode(nd, promisified, boundArgs, prop, t) and - StepSummary::step(prev, res, summary) and - result = t.append(summary) and - // Block argument-passing into 'this' when it determines the call target - not summary = CallReceiverStep() - ) - } + overlay[local] + private predicate isOverlay() { databaseMetadata("isOverlay", "true") } - private DataFlow::SourceNode trackUseNode( - DataFlow::SourceNode nd, boolean promisified, int boundArgs, string prop - ) { - result = trackUseNode(nd, promisified, boundArgs, prop, DataFlow::TypeTracker::end()) + bindingset[node] + predicate inScope(DataFlow::Node node) { not isOverlay() and exists(node) } } - /** - * Gets a node that is inter-procedurally reachable from `nd`, which is a use of some node. - */ - cached - DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { - result = trackUseNode(nd, false, 0, "") - } + private module Stage1 = Stage; - private DataFlow::SourceNode trackDefNode(DataFlow::Node nd, DataFlow::TypeBackTracker t) { - t.start() and - rhs(_, nd) and - result = nd.getALocalSource() - or - // additional backwards step from `require('m')` to `exports` or `module.exports` in m - exists(Import imp | imp.getImportedModuleNodeStrict() = trackDefNode(nd, t.continue()) | - result = DataFlow::exportsVarNode(imp.getImportedModule()) - or - result = DataFlow::moduleVarNode(imp.getImportedModule()).getAPropertyRead("exports") - ) - or - exists(ObjectExpr obj | - obj = trackDefNode(nd, t.continue()).asExpr() and - result = - obj.getAProperty() - .(SpreadProperty) - .getInit() - .(SpreadElement) - .getOperand() - .flow() - .getALocalSource() - ) - or - t = defStep(nd, result) - } + overlay[local] + private module Stage1Local { + predicate use(TApiNode node, DataFlow::Node ref) = forceLocal(Stage1::use/2)(node, ref) - /** - * Holds if `nd`, which is a def of an API-graph node, can be reached in zero or more potentially - * inter-procedural steps from some intermediate node, and `prev` flows into that intermediate node - * in one step. The entire flow is described by the resulting `TypeTracker`. - * - * This predicate exists solely to enforce a better join order in `trackDefNode` above. - */ - pragma[noopt] - private DataFlow::TypeBackTracker defStep(DataFlow::Node nd, DataFlow::SourceNode prev) { - exists(DataFlow::TypeBackTracker t, StepSummary summary, DataFlow::Node next | - next = trackDefNode(nd, t) and - StepSummary::step(prev, next, summary) and - result = t.prepend(summary) and - // Block argument-passing steps from 'this' back to a receiver when it determines the call target - not summary = CallReceiverStep() - ) - } + predicate rhs(TApiNode node, DataFlow::Node def) = forceLocal(Stage1::rhs/2)(node, def) - /** - * Gets a node that inter-procedurally flows into `nd`, which is a definition of some node. - */ - cached - DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { - result = trackDefNode(nd, DataFlow::TypeBackTracker::end()) - } + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) = + forceLocal(Stage1::trackUseNode/1)(nd, result) - private DataFlow::SourceNode awaited(DataFlow::InvokeNode call, DataFlow::TypeTracker t) { - t.startInPromise() and - exists(MkSyntheticCallbackArg(_, _, call)) and - result = call - or - exists(DataFlow::TypeTracker t2 | result = awaited(call, t2).track(t2, t)) + DataFlow::SourceNode trackUseNodeAnyState(DataFlow::SourceNode nd) = + forceLocal(Stage1::trackUseNodeAnyState/1)(nd, result) + + DataFlow::SourceNode trackDefNode(DataFlow::SourceNode nd) = + forceLocal(Stage1::trackDefNode/1)(nd, result) + + DataFlow::SourceNode trackDefNodeAnyState(DataFlow::Node nd) = + forceLocal(Stage1::trackDefNodeAnyState/1)(nd, result) + + predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) = + forceLocal(Stage1::edge/3)(pred, lbl, succ) + + DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) = + forceLocal(Stage1::getAPromisifiedInvocation/3)(callee, bound, succ, result) } - /** - * Gets a node holding the resolved value of promise `call`. - */ - private DataFlow::Node awaited(DataFlow::InvokeNode call) { - result = awaited(call, DataFlow::TypeTracker::end()) + private module Stage2Input implements StageInputSig { + overlay[global] + pragma[nomagic] + private predicate isInOverlayChangedFile(DataFlow::Node node) { + overlayChangedFiles(node.getFile().getAbsolutePath()) + } + + bindingset[node] + overlay[global] + pragma[inline_late] + private predicate isInOverlayChangedFileLate(DataFlow::Node node) { + isInOverlayChangedFile(node) + } + + pragma[nomagic] + private predicate stepIntoOverlay(DataFlow::Node node1, DataFlow::Node node2) { + StepSummary::step(node1, node2, _) and + isInOverlayChangedFile(node2) and + not isInOverlayChangedFileLate(node1) and + hasSemanticsLate(node1) + } + + pragma[nomagic] + private predicate shouldTrackIntoOverlay(DataFlow::SourceNode nd) { + exists(DataFlow::Node overlayNode | + stepIntoOverlay(Stage1Local::trackUseNodeAnyState(nd), overlayNode) + ) + } + + pragma[nomagic] + predicate isAdditionalUseRoot(Node node) { + exists(DataFlow::Node ref | + shouldTrackIntoOverlay(ref) and + Stage1Local::use(node, ref) + ) + } + + pragma[nomagic] + private predicate stepOutOfOverlay(DataFlow::Node node1, DataFlow::Node node2) { + StepSummary::step(node1, node2, _) and + isInOverlayChangedFile(node1) and + not isInOverlayChangedFileLate(node2) and + hasSemanticsLate(node2) + } + + pragma[nomagic] + private predicate shouldBacktrackIntoOverlay(DataFlow::SourceNode nd) { + exists(DataFlow::Node overlayNode | + stepOutOfOverlay(overlayNode, Stage1Local::trackDefNodeAnyState(nd)) + ) + } + + pragma[nomagic] + predicate isAdditionalDefRoot(Node node) { + exists(DataFlow::Node def | + shouldBacktrackIntoOverlay(def) and + Stage1Local::rhs(node, def) + ) + } + + bindingset[node] + predicate inScope(DataFlow::Node node) { isInOverlayChangedFile(node) } } - /** - * Holds if there is an edge from `pred` to `succ` in the API graph that is labeled with `lbl`. - */ + private module Stage2 = Stage; + cached - predicate edge(TApiNode pred, Label::ApiLabel lbl, TApiNode succ) { - Stages::ApiStage::ref() and - exists(string m | - pred = MkRoot() and - lbl = Label::moduleLabel(m) - | - succ = MkModuleDef(m) + private module Cached { + cached + predicate rhs(TApiNode nd, DataFlow::Node rhs) { + Stage1Local::rhs(nd, rhs) or - succ = MkModuleUse(m) - ) - or - exists(string m | - pred = MkModuleDef(m) and - lbl = Label::member("exports") and - succ = MkModuleExport(m) + Stage2::rhs(nd, rhs) + } + + cached + predicate use(TApiNode nd, DataFlow::Node ref) { + Stage1Local::use(nd, ref) or - pred = MkModuleUse(m) and - lbl = Label::member("exports") and - succ = MkModuleImport(m) - ) - or - exists(DataFlow::SourceNode ref | - use(pred, lbl, ref) and - succ = MkUse(ref) - ) - or - exists(DataFlow::Node rhs | rhs(pred, lbl, rhs) | - succ = MkDef(rhs) + Stage2::use(nd, ref) + } + + cached + DataFlow::SourceNode trackUseNode(DataFlow::SourceNode nd) { + result = Stage1Local::trackUseNode(nd) or - exists(DataFlow::ClassNode cls | - cls.getAnInstanceReference().flowsTo(rhs) and - succ = MkClassInstance(cls) - ) - ) - or - exists(DataFlow::Node def | - rhs(pred, def) and - lbl = Label::instance() and - succ = MkClassInstance(trackDefNode(def)) - ) - or - exists(string moduleName, string exportName | - pred = MkModuleImport(moduleName) and - lbl = Label::member(exportName) and - succ = MkTypeUse(moduleName, exportName) - ) - or - exists(DataFlow::Node nd, DataFlow::FunctionNode f | - f.getFunction().isAsync() and - pred = MkDef(nd) and - f = trackDefNode(nd) and - lbl = Label::return() and - succ = MkDef(f.getReturnNode()) - ) - or - exists(int bound, DataFlow::InvokeNode call | - lbl = Label::parameter(bound + call.getNumArgument()) and - call = getAPromisifiedInvocation(pred, bound, succ) - ) + result = Stage2::trackUseNode(nd) + } + + cached + DataFlow::SourceNode trackDefNode(DataFlow::Node nd) { + result = Stage1Local::trackDefNode(nd) + or + result = Stage2::trackDefNode(nd) + } + + cached + predicate edge(Node pred, Label::ApiLabel lbl, Node succ) { + Stage1Local::edge(pred, lbl, succ) + or + Stage2::edge(pred, lbl, succ) + } + + cached + DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { + result = Stage1Local::getAPromisifiedInvocation(callee, bound, succ) + or + result = Stage2::getAPromisifiedInvocation(callee, bound, succ) + } + } + + import Cached + + private module Debug { + private module FullInput implements StageInputSig { + pragma[inline] + predicate isAdditionalUseRoot(Node node) { none() } + + pragma[inline] + predicate isAdditionalDefRoot(Node node) { none() } + + bindingset[node] + predicate inScope(DataFlow::Node node) { any() } + } + + private module Full = Stage; + + query predicate missingDefNode(DataFlow::Node node) { + Full::rhs(_, _, node) and + not exists(MkDef(node)) + } + + query predicate missingUseNode(DataFlow::Node node) { + Full::use(_, _, node) and + not exists(MkUse(node)) + } + + query predicate lostEdge(Node pred, Label::ApiLabel lbl, Node succ) { + Full::edge(pred, lbl, succ) and + not Cached::edge(pred, lbl, succ) + } + + query predicate counts(int numEdges, int numOverlayEdges, float ratio) { + numEdges = count(Node pred, Label::ApiLabel lbl, Node succ | Full::edge(pred, lbl, succ)) and + numOverlayEdges = + count(Node pred, Label::ApiLabel lbl, Node succ | Stage2::edge(pred, lbl, succ)) and + ratio = numOverlayEdges / numEdges.(float) + } } /** @@ -1485,18 +1735,6 @@ module API { /** Gets the shortest distance from the root to `nd` in the API graph. */ cached int distanceFromRoot(TApiNode nd) = shortestDistances(MkRoot/0, edge/2)(_, nd, result) - - /** - * Gets a call to a promisified function represented by `callee` where - * `bound` arguments have been bound. - */ - cached - DataFlow::InvokeNode getAPromisifiedInvocation(TApiNode callee, int bound, TApiNode succ) { - exists(DataFlow::SourceNode src | - Impl::use(callee, src) and - succ = Impl::MkSyntheticCallbackArg(src, bound, result) - ) - } } /** @@ -1556,6 +1794,7 @@ module API { class NewNode extends InvokeNode, DataFlow::NewNode { } /** Provides classes modeling the various edges (labels) in the API graph. */ + overlay[local] module Label { /** A label in the API-graph */ class ApiLabel extends TLabel { @@ -1594,6 +1833,7 @@ module API { * This is to support code patterns where the property name is actually constant, * but the property name has been factored into a library. */ + overlay[global] private string getAnIndirectPropName(DataFlow::PropRef ref) { exists(DataFlow::Node pred | FlowSteps::propertyFlowStep(pred, ref.getPropertyNameExpr().flow()) and @@ -1604,16 +1844,19 @@ module API { /** * Gets unique result of `getAnIndirectPropName` if there is one. */ + overlay[global] private string getIndirectPropName(DataFlow::PropRef ref) { result = unique(string s | s = getAnIndirectPropName(ref)) } + overlay[global] pragma[nomagic] private predicate isEnumeratedPropName(DataFlow::Node node) { node.getAPredecessor*() instanceof EnumeratedPropName } /** Gets the `member` edge label for the given property reference. */ + overlay[global] ApiLabel memberFromRef(DataFlow::PropRef pr) { exists(string pn | pn = pr.getPropertyName() or pn = getIndirectPropName(pr) | result = member(pn) and @@ -1680,9 +1923,17 @@ module API { MkLabelInstance() or MkLabelContent(DataFlow::Content content) or MkLabelMember(string name) { - name instanceof PropertyName + name instanceof ContentPrivate::PropertyName + or + name = any(DataFlow::PropRef pr).getPropertyName() + or + exists(AccessPath::getAnAssignmentTo(_, name)) or - exists(Impl::MkTypeUse(_, name)) + name = DataFlow::PseudoProperties::arrayLikeElement() + or + name = any(TypeAccess t).getIdentifier().getName() + or + name = any(Expr s).getStringValue() } or MkLabelParameter(int i) { i = @@ -1885,3 +2136,14 @@ private Module importableModule(string m) { m = pkg.getPackageName() ) } + +overlay[local] +private predicate isDeclaredPackageName(string m) { + m = any(PackageJson pkg).getDeclaredPackageName() +} + +overlay[local] +private predicate isImportedPackageName(string m) { + m = any(Import imprt).getImportedPathString() and + m.regexpMatch("[^./].*") +} diff --git a/javascript/ql/lib/semmle/javascript/ApiGraphs2.qll b/javascript/ql/lib/semmle/javascript/ApiGraphs2.qll new file mode 100644 index 000000000000..18624595e49b --- /dev/null +++ b/javascript/ql/lib/semmle/javascript/ApiGraphs2.qll @@ -0,0 +1,220 @@ +private import javascript +private import semmle.javascript.dataflow.internal.StepSummary + +private newtype TLabel = + MkMemberLabel(PropertyName prop) or + MkArgumentLabel(int n) { exists(any(DataFlow::InvokeNode i).getArgument(n)) } or + MkParameterLabel(int n) { exists(any(DataFlow::FunctionNode i).getParameter(n)) } + +class Label extends TLabel { + string asMember() { this = MkMemberLabel(result) } + + int asArgumentIndex() { this = MkArgumentLabel(result) } + + int asParameterIndex() { this = MkParameterLabel(result) } + + string toString() { + result = "Member[" + this.asMember() + "]" or + result = "Argument[" + this.asArgumentIndex() + "]" or + result = "Parameter[" + this.asParameterIndex() + "]" + } +} + +module API { + private class Node = DataFlow::Node; + + predicate useToUseStep(Node node1, Label label, Node node2) { + exists(DataFlow::PropRead read | + node1 = read.getBase() and + node2 = read and + label.asMember() = read.getPropertyName() + ) + } + + predicate defToDefStep(Node node1, Label label, Node node2) { + exists(DataFlow::PropWrite write | + node1 = write.getBase().getALocalSource() and + node2 = write.getRhs() and + label.asMember() = write.getPropertyName() + ) + } + + predicate defToUseStep(Node node1, Label label, Node node2) { + exists(DataFlow::FunctionNode fun, int i | + node1 = fun and + node2 = fun.getParameter(i) and + label.asParameterIndex() = i + ) + } + + predicate useToDefStep(Node node1, Label label, Node node2) { + exists(DataFlow::InvokeNode node, int i | + node1 = node.getCalleeNode() and + node2 = node.getArgument(i) and + label.asArgumentIndex() = i + ) + } + + signature module DeepFlowInputSig { + predicate isEntryPointUse(Node node); + + predicate isEntryPointDef(Node node); + + bindingset[node] + predicate shouldInclude(Node node); + } + + overlay[local?] + module DeepFlow { + private import S + + private predicate isUseNodeRoot(DataFlow::SourceNode node) { + isEntryPointUse(node) + or + useToUseStep(trackUse(_), _, node) and shouldInclude(node) + or + defToUseStep(trackDef(_), _, node) and shouldInclude(node) + } + + DataFlow::SourceNode trackUse(DataFlow::SourceNode node, DataFlow::TypeTracker t) { + isUseNodeRoot(node) and + result = node and + t.start() + or + exists(DataFlow::TypeTracker t2 | result = trackUse(node, t2).track(t2, t)) + } + + DataFlow::SourceNode trackUse(DataFlow::SourceNode node) { + result = trackUse(node, DataFlow::TypeTracker::end()) + } + + private predicate isDefNodeRoot(DataFlow::Node node) { + isEntryPointDef(node) + or + useToDefStep(trackUse(_), _, node) and shouldInclude(node) + or + defToDefStep(trackDef(_), _, node) and shouldInclude(node) + } + + DataFlow::SourceNode trackDef(DataFlow::Node node, DataFlow::TypeBackTracker t) { + isDefNodeRoot(node) and + result = node.getALocalSource() and + t.start() + or + exists(DataFlow::TypeBackTracker t2 | result = trackDef(node, t2).backtrack(t2, t)) + } + + DataFlow::SourceNode trackDef(DataFlow::Node node) { + result = trackDef(node, DataFlow::TypeBackTracker::end()) + } + } + + private module Input1 implements DeepFlowInputSig { + predicate isEntryPointUse(Node node) { + exists(Import imprt | + imprt.getImportedPathString().regexpMatch("[^./].*") and + node = imprt.getImportedModuleNode() + ) + } + + predicate isEntryPointDef(Node node) { + exists(PackageJson pkg | + not pkg.isPrivate() and + node = + [pkg.getMainModule().getAnExportedValue(_), pkg.getMainModule().getABulkExportedNode()] + ) + } + + bindingset[node] + predicate shouldInclude(Node node) { any() } + } + + private module DeepFlow1 = DeepFlow; + + overlay[local] + DataFlow::SourceNode trackUseLocal(DataFlow::SourceNode node) = + forceLocal(DeepFlow1::trackUse/1)(node, result) + + overlay[local] + DataFlow::SourceNode trackDefLocal(DataFlow::Node node) = + forceLocal(DeepFlow1::trackDef/1)(node, result) + + bindingset[node] + overlay[global] + pragma[inline_late] + private predicate isInOverlayChangedFile(DataFlow::Node node) { + overlayChangedFiles(node.getFile().getAbsolutePath()) + } + + predicate stepIntoOverlay(Node node1, Node node2, StepSummary summary) { + StepSummary::smallstep(node1, node2, summary) and + not isInOverlayChangedFile(node1) and + isInOverlayChangedFile(node2) + } + + predicate stepOutOfOverlay(Node node1, Node node2, StepSummary summary) { + StepSummary::smallstep(node1, node2, summary) and + isInOverlayChangedFile(node1) and + not isInOverlayChangedFile(node2) + } + + private module Input2 implements DeepFlowInputSig { + predicate isEntryPointUse(Node node) { + stepIntoOverlay(trackUseLocal(node).getALocalUse(), _, _) + } + + predicate isEntryPointDef(Node node) { stepOutOfOverlay(_, trackDefLocal(node), _) } + + predicate shouldInclude(Node node) { isInOverlayChangedFile(node) } + } + + private module DeepFlow2 = DeepFlow; + + DataFlow::SourceNode trackUseFinal(DataFlow::SourceNode node) { + result = DeepFlow1::trackUse(node) + or + result = DeepFlow2::trackUse(node) + } + + DataFlow::SourceNode trackDefFinal(DataFlow::Node node) { + result = DeepFlow1::trackDef(node) + or + result = DeepFlow2::trackDef(node) + } + + module Debug { + query DataFlow::SourceNode trackUseLostAfterForceLocal(DataFlow::SourceNode node) { + result = DeepFlow1::trackUse(node) and + not result = trackUseLocal(node) + } + + query DataFlow::SourceNode trackDefLostAfterForceLocal(DataFlow::Node node) { + result = DeepFlow1::trackDef(node) and + not result = trackDefLocal(node) + } + + query predicate trackUseSecondPass = DeepFlow2::trackUse/1; + + query predicate trackDefSecondPass = DeepFlow2::trackDef/1; + + query DataFlow::SourceNode trackUseLost(DataFlow::SourceNode node) { + result = DeepFlow1::trackUse(node) and + not result = trackUseFinal(node) + } + + query DataFlow::SourceNode trackDefLost(DataFlow::Node node) { + result = DeepFlow1::trackDef(node) and + not result = trackDefFinal(node) + } + + query DataFlow::SourceNode trackUseGained(DataFlow::SourceNode node) { + not result = DeepFlow1::trackUse(node) and + result = trackUseFinal(node) + } + + query DataFlow::SourceNode trackDefGained(DataFlow::Node node) { + not result = DeepFlow1::trackDef(node) and + result = trackDefFinal(node) + } + } +} diff --git a/javascript/ql/lib/semmle/javascript/Arrays.qll b/javascript/ql/lib/semmle/javascript/Arrays.qll index d85221858866..58a70fe357a8 100644 --- a/javascript/ql/lib/semmle/javascript/Arrays.qll +++ b/javascript/ql/lib/semmle/javascript/Arrays.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript private import semmle.javascript.dataflow.InferredTypes private import semmle.javascript.dataflow.internal.PreCallGraphStep diff --git a/javascript/ql/lib/semmle/javascript/Base64.qll b/javascript/ql/lib/semmle/javascript/Base64.qll index 4f548fe18738..59c1c8fdee51 100644 --- a/javascript/ql/lib/semmle/javascript/Base64.qll +++ b/javascript/ql/lib/semmle/javascript/Base64.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with base64 encoders and decoders. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/BasicBlocks.qll b/javascript/ql/lib/semmle/javascript/BasicBlocks.qll index dfd9c3956b18..e3fd0bc8b140 100644 --- a/javascript/ql/lib/semmle/javascript/BasicBlocks.qll +++ b/javascript/ql/lib/semmle/javascript/BasicBlocks.qll @@ -2,5 +2,7 @@ * Provides classes for working with basic blocks, and predicates for computing * liveness information for local variables. */ +overlay[local?] +module; import internal.BasicBlockInternal::Public diff --git a/javascript/ql/lib/semmle/javascript/CFG.qll b/javascript/ql/lib/semmle/javascript/CFG.qll index 95e1e9aef72a..2270ddfeaaf3 100644 --- a/javascript/ql/lib/semmle/javascript/CFG.qll +++ b/javascript/ql/lib/semmle/javascript/CFG.qll @@ -272,6 +272,8 @@ * Note that the `import` statement as a whole is part of the CFG of the body, while its single * import specifier `x as y` forms part of the preamble. */ +overlay[local] +module; import javascript private import internal.StmtContainers diff --git a/javascript/ql/lib/semmle/javascript/CanonicalNames.qll b/javascript/ql/lib/semmle/javascript/CanonicalNames.qll index 87f7c25b36de..1e851e3664d1 100644 --- a/javascript/ql/lib/semmle/javascript/CanonicalNames.qll +++ b/javascript/ql/lib/semmle/javascript/CanonicalNames.qll @@ -1,6 +1,7 @@ /** * Provides classes for working with name resolution of namespaces and types. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll b/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll index 5c8dd2bdd06e..ac8281868c4c 100644 --- a/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll +++ b/javascript/ql/lib/semmle/javascript/CharacterEscapes.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about character escapes in literals. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Classes.qll b/javascript/ql/lib/semmle/javascript/Classes.qll index 394ab7910276..2485553370c6 100644 --- a/javascript/ql/lib/semmle/javascript/Classes.qll +++ b/javascript/ql/lib/semmle/javascript/Classes.qll @@ -4,6 +4,8 @@ * Class declarations and class expressions are modeled by (QL) classes `ClassDeclaration` * and `ClassExpression`, respectively, which are both subclasses of `ClassDefinition`. */ +overlay[local] +module; import javascript @@ -119,6 +121,7 @@ class ClassOrInterface extends @class_or_interface, TypeParameterized { * * Anonymous classes and interfaces do not have a canonical name. */ + overlay[global] deprecated TypeName getTypeName() { result.getADefinition() = this } /** @@ -253,6 +256,7 @@ class ClassDefinition extends @class_definition, ClassOrInterface, AST::ValueNod /** * Gets the definition of the super class of this class, if it can be determined. */ + overlay[global] ClassDefinition getSuperClassDefinition() { result = this.getSuperClass().analyze().getAValue().(AbstractClass).getClass() } @@ -580,6 +584,7 @@ class MemberDeclaration extends @property, Documentable { int getMemberIndex() { properties(this, _, result, _, _) } /** Holds if the name of this member is computed by an impure expression. */ + overlay[global] predicate hasImpureNameExpr() { this.isComputed() and this.getNameExpr().isImpure() } /** diff --git a/javascript/ql/lib/semmle/javascript/Closure.qll b/javascript/ql/lib/semmle/javascript/Closure.qll index c31698333393..fd13023b2e6e 100644 --- a/javascript/ql/lib/semmle/javascript/Closure.qll +++ b/javascript/ql/lib/semmle/javascript/Closure.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with the Closure-Library module system. */ +overlay[local] +module; import javascript @@ -40,6 +42,7 @@ module Closure { /** * A reference to a Closure namespace. */ + overlay[global] deprecated class ClosureNamespaceRef extends DataFlow::Node instanceof ClosureNamespaceRef::Range { /** * Gets the namespace being referenced. @@ -47,6 +50,7 @@ module Closure { string getClosureNamespace() { result = super.getClosureNamespace() } } + overlay[global] deprecated module ClosureNamespaceRef { /** * A reference to a Closure namespace. @@ -64,9 +68,11 @@ module Closure { /** * A data flow node that returns the value of a closure namespace. */ + overlay[global] deprecated class ClosureNamespaceAccess extends ClosureNamespaceRef instanceof ClosureNamespaceAccess::Range { } + overlay[global] deprecated module ClosureNamespaceAccess { /** * A data flow node that returns the value of a closure namespace. @@ -79,6 +85,7 @@ module Closure { /** * A call to a method on the `goog.` namespace, as a closure reference. */ + overlay[global] abstract deprecated private class DefaultNamespaceRef extends DataFlow::MethodCallNode, ClosureNamespaceRef::Range { @@ -91,6 +98,7 @@ module Closure { * Holds if `node` is the data flow node corresponding to the expression in * a top-level expression statement. */ + overlay[global] deprecated private predicate isTopLevelExpr(DataFlow::Node node) { any(TopLevel tl).getAChildStmt().(ExprStmt).getExpr().flow() = node } @@ -98,6 +106,7 @@ module Closure { /** * A top-level call to `goog.provide`. */ + overlay[global] deprecated private class DefaultClosureProvideCall extends DefaultNamespaceRef { DefaultClosureProvideCall() { this.getMethodName() = "provide" and @@ -108,12 +117,14 @@ module Closure { /** * A top-level call to `goog.provide`. */ + overlay[global] deprecated class ClosureProvideCall extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureProvideCall { } /** * A call to `goog.require`. */ + overlay[global] deprecated private class DefaultClosureRequireCall extends DefaultNamespaceRef, ClosureNamespaceAccess::Range { @@ -123,12 +134,14 @@ module Closure { /** * A call to `goog.require`. */ + overlay[global] deprecated class ClosureRequireCall extends ClosureNamespaceAccess, DataFlow::MethodCallNode instanceof DefaultClosureRequireCall { } /** * A top-level call to `goog.module` or `goog.declareModuleId`. */ + overlay[global] deprecated private class DefaultClosureModuleDeclaration extends DefaultNamespaceRef { DefaultClosureModuleDeclaration() { (this.getMethodName() = "module" or this.getMethodName() = "declareModuleId") and @@ -139,6 +152,7 @@ module Closure { /** * A top-level call to `goog.module` or `goog.declareModuleId`. */ + overlay[global] deprecated class ClosureModuleDeclaration extends ClosureNamespaceRef, DataFlow::MethodCallNode instanceof DefaultClosureModuleDeclaration { } @@ -156,6 +170,7 @@ module Closure { /** * Gets the call to `goog.module` or `goog.declareModuleId` in this module. */ + overlay[global] deprecated ClosureModuleDeclaration getModuleDeclaration() { result.getTopLevel() = this } /** @@ -181,6 +196,7 @@ module Closure { result = this.getScope().getVariable("exports") } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { exists(DataFlow::PropWrite write, Expr base | result = write.getRhs() and @@ -193,6 +209,7 @@ module Closure { ) } + overlay[global] override DataFlow::Node getABulkExportedNode() { result = this.getExportsVariable().getAnAssignedExpr().flow() } @@ -232,6 +249,7 @@ module Closure { /** * Holds if `name` is a closure namespace, including proper namespace prefixes. */ + overlay[global] pragma[noinline] predicate isClosureNamespace(string name) { exists(string namespace | @@ -253,6 +271,7 @@ module Closure { * Holds if a prefix of `name` is a closure namespace. */ bindingset[name] + overlay[global] private predicate hasClosureNamespacePrefix(string name) { isClosureNamespace(name.substring(0, name.indexOf("."))) or @@ -262,6 +281,7 @@ module Closure { /** * Gets the closure namespace path addressed by the given data flow node, if any. */ + overlay[global] string getClosureNamespaceFromSourceNode(DataFlow::SourceNode node) { node = AccessPath::getAReferenceOrAssignmentTo(result) and hasClosureNamespacePrefix(result) @@ -270,6 +290,7 @@ module Closure { /** * Gets the closure namespace path written to by the given property write, if any. */ + overlay[global] string getWrittenClosureNamespace(DataFlow::PropWrite node) { node.getRhs() = AccessPath::getAnAssignmentTo(result) and hasClosureNamespacePrefix(result) @@ -278,6 +299,7 @@ module Closure { /** * Gets a data flow node that refers to the given value exported from a Closure module. */ + overlay[global] DataFlow::SourceNode moduleImport(string moduleName) { getClosureNamespaceFromSourceNode(result) = moduleName } @@ -285,6 +307,7 @@ module Closure { /** * A call to `goog.bind`, as a partial function invocation. */ + overlay[global] private class BindCall extends DataFlow::PartialInvokeNode::Range, DataFlow::CallNode { BindCall() { this = moduleImport("goog.bind").getACall() } diff --git a/javascript/ql/lib/semmle/javascript/Collections.qll b/javascript/ql/lib/semmle/javascript/Collections.qll index f3e3eb5a61db..648dd752e1fd 100644 --- a/javascript/ql/lib/semmle/javascript/Collections.qll +++ b/javascript/ql/lib/semmle/javascript/Collections.qll @@ -3,6 +3,8 @@ * Currently [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) and * [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) are implemented. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.StepSummary diff --git a/javascript/ql/lib/semmle/javascript/Comments.qll b/javascript/ql/lib/semmle/javascript/Comments.qll index 889843728a25..46ce8b8a4ba9 100644 --- a/javascript/ql/lib/semmle/javascript/Comments.qll +++ b/javascript/ql/lib/semmle/javascript/Comments.qll @@ -1,4 +1,6 @@ /** Provides classes for working with JavaScript comments. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Concepts.qll b/javascript/ql/lib/semmle/javascript/Concepts.qll index 70fe76ae5f13..b5d7ddd0d9ee 100644 --- a/javascript/ql/lib/semmle/javascript/Concepts.qll +++ b/javascript/ql/lib/semmle/javascript/Concepts.qll @@ -3,6 +3,8 @@ * access or system command execution, for which individual framework libraries * provide concrete subclasses. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.sharedlib.DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/Constants.qll b/javascript/ql/lib/semmle/javascript/Constants.qll index 21e70869c67c..b0b4a6c03eec 100644 --- a/javascript/ql/lib/semmle/javascript/Constants.qll +++ b/javascript/ql/lib/semmle/javascript/Constants.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with expressions that evaluate to constant values. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/DOM.qll b/javascript/ql/lib/semmle/javascript/DOM.qll index 21854c1a9d0e..87e5f66f87f4 100644 --- a/javascript/ql/lib/semmle/javascript/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/DOM.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with DOM elements. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Templating @@ -192,6 +194,7 @@ module DOM { * A data flow node or other program element that may refer to * a DOM element. */ + overlay[global] abstract class Element extends Locatable { ElementDefinition defn; diff --git a/javascript/ql/lib/semmle/javascript/DefUse.qll b/javascript/ql/lib/semmle/javascript/DefUse.qll index a9d021f939e9..95cf57d543d2 100644 --- a/javascript/ql/lib/semmle/javascript/DefUse.qll +++ b/javascript/ql/lib/semmle/javascript/DefUse.qll @@ -1,4 +1,6 @@ /** Provides classes and predicates for working with variable definitions and uses. */ +overlay[local] +module; import javascript @@ -231,6 +233,7 @@ class VarUse extends ControlFlowNode, @varref instanceof RValue { * * For global variables, each definition is considered to reach each use. */ + overlay[global] VarDef getADef() { result = this.getSsaVariable().getDefinition().getAContributingVarDef() or result.getAVariable() = this.getVariable().(GlobalVariable) @@ -241,5 +244,6 @@ class VarUse extends ControlFlowNode, @varref instanceof RValue { * * This predicate is only defined for variables that can be SSA-converted. */ + overlay[global] SsaVariable getSsaVariable() { result.getAUse() = this } } diff --git a/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll b/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll index 96bbea0e55cc..364a0d85b415 100644 --- a/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll +++ b/javascript/ql/lib/semmle/javascript/DefensiveProgramming.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with defensive programming patterns. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll index a81e8828d316..1dbdf6980116 100644 --- a/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll +++ b/javascript/ql/lib/semmle/javascript/DynamicPropertyAccess.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with dynamic property accesses. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/E4X.qll b/javascript/ql/lib/semmle/javascript/E4X.qll index cd112d60664e..ce917c48cff3 100644 --- a/javascript/ql/lib/semmle/javascript/E4X.qll +++ b/javascript/ql/lib/semmle/javascript/E4X.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with E4X. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll index e584697c1e44..6eee9ea56e50 100644 --- a/javascript/ql/lib/semmle/javascript/ES2015Modules.qll +++ b/javascript/ql/lib/semmle/javascript/ES2015Modules.qll @@ -1,4 +1,6 @@ /** Provides classes for working with ECMAScript 2015 modules. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -29,11 +31,13 @@ class ES2015Module extends Module { /** Gets an export declaration in this module. */ ExportDeclaration getAnExport() { result.getTopLevel() = this } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { exists(ExportDeclaration ed | ed = this.getAnExport() and result = ed.getSourceNode(name)) } /** Holds if this module exports variable `v` under the name `name`. */ + overlay[global] predicate exportsAs(LexicalName v, string name) { this.getAnExport().exportsAs(v, name) } override predicate isStrict() { @@ -50,6 +54,7 @@ class ES2015Module extends Module { * When a module has both named and `default` exports, the non-standard interpretation can lead to * ambiguities, so we only allow the standard interpretation in that case. */ + overlay[global] predicate hasBothNamedAndDefaultExports() { hasNamedExports(this) and hasDefaultExport(this) @@ -59,6 +64,7 @@ class ES2015Module extends Module { /** * Holds if `mod` contains one or more named export declarations other than `default`. */ +overlay[global] private predicate hasNamedExports(ES2015Module mod) { mod.getAnExport().(ExportNamedDeclaration).getASpecifier().getExportedName() != "default" or @@ -71,6 +77,7 @@ private predicate hasNamedExports(ES2015Module mod) { /** * Holds if this module contains a default export. */ +overlay[global] private predicate hasDefaultExport(ES2015Module mod) { // export default foo; mod.getAnExport() instanceof ExportDefaultDeclaration @@ -172,6 +179,7 @@ class ImportDeclaration extends Stmt, Import, @import_declaration { } /** A literal path expression appearing in an `import` declaration. */ +overlay[global] deprecated private class LiteralImportPath extends PathExpr, ConstantString { LiteralImportPath() { exists(ImportDeclaration req | this = req.getChildExpr(-1)) } @@ -198,6 +206,7 @@ deprecated private class LiteralImportPath extends PathExpr, ConstantString { */ class ImportSpecifier extends Expr, @import_specifier { /** Gets the import declaration in which this specifier appears. */ + overlay[global] ImportDeclaration getImportDeclaration() { result.getASpecifier() = this } /** Gets the imported symbol; undefined for default and namespace import specifiers. */ @@ -297,6 +306,7 @@ class BulkImportDeclaration extends ImportDeclaration { * import console, { log } from 'console'; * ``` */ +overlay[global] class SelectiveImportDeclaration extends ImportDeclaration { SelectiveImportDeclaration() { not this instanceof BulkImportDeclaration } @@ -330,9 +340,11 @@ class SelectiveImportDeclaration extends ImportDeclaration { */ abstract class ExportDeclaration extends Stmt, @export_declaration { /** Gets the module to which this export declaration belongs. */ + overlay[global] ES2015Module getEnclosingModule() { this = result.getAnExport() } /** Holds if this export declaration exports variable `v` under the name `name`. */ + overlay[global] abstract predicate exportsAs(LexicalName v, string name); /** @@ -356,6 +368,7 @@ abstract class ExportDeclaration extends Stmt, @export_declaration { * exports under the same name. In particular, its source node belongs * to module `a` or possibly to some other module from which `a` re-exports. */ + overlay[global] abstract DataFlow::Node getSourceNode(string name); /** Holds if is declared with the `type` keyword, so only types are exported. */ @@ -407,11 +420,13 @@ class BulkReExportDeclaration extends ReExportDeclaration, @export_all_declarati /** Gets the name of the module from which this declaration re-exports. */ override ConstantString getImportedPath() { result = this.getChildExpr(0) } + overlay[global] override predicate exportsAs(LexicalName v, string name) { this.getReExportedES2015Module().exportsAs(v, name) and not isShadowedFromBulkExport(this, name) } + overlay[global] override DataFlow::Node getSourceNode(string name) { result = this.getReExportedES2015Module().getAnExport().getSourceNode(name) } @@ -430,6 +445,7 @@ class BulkReExportDeclaration extends ReExportDeclaration, @export_all_declarati * At runtime, the interface `X` will have been removed, so `X` is actually re-exported anyway, * but we ignore this subtlety. */ +overlay[global] private predicate isShadowedFromBulkExport(BulkReExportDeclaration reExport, string name) { exists(ExportNamedDeclaration other | other.getTopLevel() = reExport.getEnclosingModule() | other.getAnExportedDecl().getName() = name @@ -452,6 +468,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declar /** Gets the operand statement or expression that is exported by this declaration. */ ExprOrStmt getOperand() { result = this.getChild(0) } + overlay[global] override predicate exportsAs(LexicalName v, string name) { name = "default" and v = this.getADecl().getVariable() } @@ -464,6 +481,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declar ) } + overlay[global] override DataFlow::Node getSourceNode(string name) { name = "default" and result = DataFlow::valueNode(this.getOperand()) } @@ -506,6 +524,7 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio /** Gets the variable declaration, if any, exported by this named export. */ VarDecl getADecl() { result = this.getAnExportedDecl() } + overlay[global] override predicate exportsAs(LexicalName v, string name) { exists(LexicalDecl vd | vd = this.getAnExportedDecl() | name = vd.getName() and v = vd.getALexicalName() @@ -518,6 +537,7 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio ) } + overlay[global] override DataFlow::Node getSourceNode(string name) { exists(VarDef d | d.getTarget() = this.getADecl() | name = d.getTarget().(VarDecl).getName() and @@ -555,6 +575,7 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio private import semmle.javascript.dataflow.internal.PreCallGraphStep +overlay[global] private class ExportNamespaceStep extends PreCallGraphStep { override predicate storeStep(DataFlow::Node pred, DataFlow::SourceNode succ, string prop) { exists(ExportNamedDeclaration exprt, ExportNamespaceSpecifier spec | @@ -572,6 +593,7 @@ private class ExportNamespaceStep extends PreCallGraphStep { private class TypeOnlyExportDeclaration extends ExportNamedDeclaration { TypeOnlyExportDeclaration() { this.isTypeOnly() } + overlay[global] override predicate exportsAs(LexicalName v, string name) { super.exportsAs(v, name) and not v instanceof Variable @@ -745,9 +767,11 @@ abstract class ReExportDeclaration extends ExportDeclaration { abstract ConstantString getImportedPath(); /** Gets the module from which this declaration re-exports, if it is an ES2015 module. */ + overlay[global] ES2015Module getReExportedES2015Module() { result = this.getReExportedModule() } /** Gets the module from which this declaration re-exports. */ + overlay[global] cached Module getReExportedModule() { Stages::Imports::ref() and @@ -756,6 +780,7 @@ abstract class ReExportDeclaration extends ExportDeclaration { } /** A literal path expression appearing in a re-export declaration. */ +overlay[global] deprecated private class LiteralReExportPath extends PathExpr, ConstantString { LiteralReExportPath() { exists(ReExportDeclaration bred | this = bred.getImportedPath()) } @@ -795,11 +820,13 @@ class SelectiveReExportDeclaration extends ReExportDeclaration, ExportNamedDecla class OriginalExportDeclaration extends ExportDeclaration { OriginalExportDeclaration() { not this instanceof ReExportDeclaration } + overlay[global] override predicate exportsAs(LexicalName v, string name) { this.(ExportDefaultDeclaration).exportsAs(v, name) or this.(ExportNamedDeclaration).exportsAs(v, name) } + overlay[global] override DataFlow::Node getSourceNode(string name) { result = this.(ExportDefaultDeclaration).getSourceNode(name) or result = this.(ExportNamedDeclaration).getSourceNode(name) diff --git a/javascript/ql/lib/semmle/javascript/EmailClients.qll b/javascript/ql/lib/semmle/javascript/EmailClients.qll index 3f375b4b1252..4a499b59c7a3 100644 --- a/javascript/ql/lib/semmle/javascript/EmailClients.qll +++ b/javascript/ql/lib/semmle/javascript/EmailClients.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript /** diff --git a/javascript/ql/lib/semmle/javascript/Errors.qll b/javascript/ql/lib/semmle/javascript/Errors.qll index 6a5d73566a44..518b76b53461 100644 --- a/javascript/ql/lib/semmle/javascript/Errors.qll +++ b/javascript/ql/lib/semmle/javascript/Errors.qll @@ -1,4 +1,6 @@ /** Provides classes for working with syntax errors. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Expr.qll b/javascript/ql/lib/semmle/javascript/Expr.qll index ae02511ba410..b46faf7e2b79 100644 --- a/javascript/ql/lib/semmle/javascript/Expr.qll +++ b/javascript/ql/lib/semmle/javascript/Expr.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with expressions. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -115,12 +117,14 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { string getStringValue() { Stages::Ast::ref() and result = getStringValue(this) } /** Holds if this expression is impure, that is, its evaluation could have side effects. */ + overlay[global] predicate isImpure() { any() } /** * Holds if this expression is pure, that is, its evaluation is guaranteed * to be side-effect free. */ + overlay[global] predicate isPure() { not this.isImpure() } /** @@ -153,21 +157,25 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { * Holds if this expression accesses the global variable `g`, either directly * or through the `window` object. */ + overlay[global] predicate accessesGlobal(string g) { this.flow().accessesGlobal(g) } /** * Holds if this expression may evaluate to `s`. */ + overlay[global] predicate mayHaveStringValue(string s) { this.flow().mayHaveStringValue(s) } /** * Holds if this expression may evaluate to `b`. */ + overlay[global] predicate mayHaveBooleanValue(boolean b) { this.flow().mayHaveBooleanValue(b) } /** * Holds if this expression may refer to the initial value of parameter `p`. */ + overlay[global] predicate mayReferToParameter(Parameter p) { DataFlow::parameterNode(p).flowsToExpr(this) } /** @@ -178,6 +186,7 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { * Has no result if the expression is in a JavaScript file or in a TypeScript * file that was extracted without type information. */ + overlay[global] deprecated Type getType() { ast_node_type(this, result) } /** @@ -240,21 +249,16 @@ class Expr extends @expr, ExprOrStmt, ExprOrType, AST::ValueNode { ) } - pragma[inline] - private Stmt getRawEnclosingStmt(Expr e) { - // For performance reasons, we need the enclosing statement without overrides - enclosing_stmt(e, result) - } - /** * Gets the data-flow node where exceptions thrown by this expression will * propagate if this expression causes an exception to be thrown. */ + overlay[caller] pragma[inline] DataFlow::Node getExceptionTarget() { - result = getCatchParameterFromStmt(this.getRawEnclosingStmt(this)) + result = getCatchParameterFromStmt(getRawEnclosingStmt(this)) or - not exists(getCatchParameterFromStmt(this.getRawEnclosingStmt(this))) and + not exists(getCatchParameterFromStmt(getRawEnclosingStmt(this))) and result = any(DataFlow::FunctionNode f | f.getFunction() = this.getContainer()).getExceptionalReturn() } @@ -267,6 +271,13 @@ private DataFlow::Node getCatchParameterFromStmt(Stmt stmt) { DataFlow::parameterNode(stmt.getEnclosingTryCatchStmt().getACatchClause().getAParameter()) } +overlay[caller] +pragma[inline] +private Stmt getRawEnclosingStmt(Expr e) { + // For performance reasons, we need the enclosing statement without overrides + enclosing_stmt(e, result) +} + /** * An identifier. * @@ -301,6 +312,7 @@ class Identifier extends @identifier, ExprOrType { * ``` */ class Label extends @label, Identifier, Expr { + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "Label" } @@ -330,6 +342,7 @@ class Literal extends @literal, Expr { */ string getRawValue() { literals(_, result, this) } + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "Literal" } @@ -352,6 +365,7 @@ class ParExpr extends @par_expr, Expr { override int getIntValue() { result = this.getExpression().getIntValue() } + overlay[global] override predicate isImpure() { this.getExpression().isImpure() } override Expr getUnderlyingValue() { result = this.getExpression().getUnderlyingValue() } @@ -500,6 +514,7 @@ class RegExpLiteral extends @regexp_literal, Literal, RegExpParent { * ``` */ class ThisExpr extends @this_expr, Expr { + overlay[global] override predicate isImpure() { none() } /** @@ -555,6 +570,7 @@ class ArrayExpr extends @array_expr, Expr { /** Holds if this array literal has an omitted element. */ predicate hasOmittedElement() { this.elementIsOmitted(_) } + overlay[global] override predicate isImpure() { this.getAnElement().isImpure() } override string getAPrimaryQlClass() { result = "ArrayExpr" } @@ -597,6 +613,7 @@ class ObjectExpr extends @obj_expr, Expr { */ predicate hasTrailingComma() { this.getLastToken().getPreviousToken().getValue() = "," } + overlay[global] override predicate isImpure() { this.getAProperty().isImpure() } override string getAPrimaryQlClass() { result = "ObjectExpr" } @@ -664,6 +681,7 @@ class Property extends @property, Documentable { * Holds if this property is impure, that is, the evaluation of its name or * its initializer expression could have side effects. */ + overlay[global] predicate isImpure() { this.isComputed() and this.getNameExpr().isImpure() or @@ -826,6 +844,7 @@ class FunctionExpr extends @function_expr, Expr, Function { Stages::Ast::ref() and result = Expr.super.getContainer() } + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "FunctionExpr" } @@ -846,6 +865,7 @@ class ArrowFunctionExpr extends @arrow_function_expr, Expr, Function { override StmtContainer getEnclosingContainer() { result = Expr.super.getContainer() } + overlay[global] override predicate isImpure() { none() } override Function getThisBinder() { @@ -877,6 +897,7 @@ class SeqExpr extends @seq_expr, Expr { /** Gets the last expression in this sequence. */ Expr getLastOperand() { result = this.getOperand(this.getNumOperands() - 1) } + overlay[global] override predicate isImpure() { this.getAnOperand().isImpure() } override Expr getUnderlyingValue() { result = this.getLastOperand().getUnderlyingValue() } @@ -906,6 +927,7 @@ class ConditionalExpr extends @conditional_expr, Expr { /** Gets either the 'then' or the 'else' expression of this conditional. */ Expr getABranch() { result = this.getConsequent() or result = this.getAlternate() } + overlay[global] override predicate isImpure() { this.getCondition().isImpure() or this.getABranch().isImpure() @@ -985,6 +1007,7 @@ class InvokeExpr extends @invokeexpr, Expr { * * This predicate is an approximation, computed using only local data flow. */ + overlay[global] predicate hasOptionArgument(int i, string name, Expr value) { value = this.flow().(DataFlow::InvokeNode).getOptionArgument(i, name).asExpr() } @@ -997,6 +1020,7 @@ class InvokeExpr extends @invokeexpr, Expr { * * This predicate is only populated for files extracted with full TypeScript extraction. */ + overlay[global] deprecated CallSignatureType getResolvedSignature() { invoke_expr_signature(this, result) } /** @@ -1014,6 +1038,7 @@ class InvokeExpr extends @invokeexpr, Expr { * * This predicate is only populated for files extracted with full TypeScript extraction. */ + overlay[global] deprecated CanonicalFunctionName getResolvedCalleeName() { ast_node_symbol(this, result) } /** @@ -1022,6 +1047,7 @@ class InvokeExpr extends @invokeexpr, Expr { * Note that the resolved function may be overridden in a subclass and thus is not * necessarily the actual target of this invocation at runtime. */ + overlay[global] Function getResolvedCallee() { TypeResolution::callTarget(this, result) } } @@ -1156,6 +1182,7 @@ class DotExpr extends @dot_expr, PropAccess { /** Gets the identifier specifying the name of the accessed property. */ Identifier getProperty() { result = this.getChildExpr(1) } + overlay[global] override predicate isImpure() { this.getBase().isImpure() } override string getAPrimaryQlClass() { result = "DotExpr" } @@ -1176,6 +1203,7 @@ class IndexExpr extends @index_expr, PropAccess { override string getPropertyName() { result = this.getIndex().(Literal).getValue() } + overlay[global] override predicate isImpure() { this.getBase().isImpure() or this.getIndex().isImpure() @@ -1201,6 +1229,7 @@ class UnaryExpr extends @unaryexpr, Expr { /** Gets the operator of this expression. */ string getOperator() { none() } + overlay[global] override predicate isImpure() { this.getOperand().isImpure() } override ControlFlowNode getFirstControlFlowNode() { @@ -1302,6 +1331,7 @@ class VoidExpr extends @void_expr, UnaryExpr { class DeleteExpr extends @delete_expr, UnaryExpr { override string getOperator() { result = "delete" } + overlay[global] override predicate isImpure() { any() } } @@ -1352,6 +1382,7 @@ class BinaryExpr extends @binaryexpr, Expr { /** Gets the operator of this expression. */ string getOperator() { none() } + overlay[global] override predicate isImpure() { this.getAnOperand().isImpure() } override ControlFlowNode getFirstControlFlowNode() { @@ -1617,13 +1648,19 @@ private string getConstantString(Expr e) { result = e.(TemplateElement).getValue() } +pragma[nomagic] +private predicate hasConstantStringValue(Expr e) { + exists(getConstantString(e)) + or + hasAllConstantLeafs(e.getUnderlyingValue()) +} + /** * Holds if `add` is a string-concatenation where all the transitive leafs have a constant string value. */ private predicate hasAllConstantLeafs(AddExpr add) { - forex(Expr leaf | leaf = getAnAddOperand*(add) and not exists(getAnAddOperand(leaf)) | - exists(getConstantString(leaf)) - ) + hasConstantStringValue(add.getLeftOperand()) and + hasConstantStringValue(add.getRightOperand()) } /** @@ -2233,6 +2270,7 @@ class YieldExpr extends @yield_expr, Expr { /** Holds if this is a `yield*` expression. */ predicate isDelegating() { is_delegating(this) } + overlay[global] override predicate isImpure() { any() } override ControlFlowNode getFirstControlFlowNode() { @@ -2289,6 +2327,7 @@ class ComprehensionExpr extends @comprehension_expr, Expr { /** Gets the body expression of this comprehension. */ Expr getBody() { result = this.getChildExpr(0) } + overlay[global] override predicate isImpure() { this.getABlock().isImpure() or this.getAFilter().isImpure() or @@ -2349,6 +2388,7 @@ class ComprehensionBlock extends @comprehension_block, Expr { /** Gets the domain over which this comprehension block iterates. */ Expr getDomain() { result = this.getChildExpr(1) } + overlay[global] override predicate isImpure() { this.getIterator().isImpure() or this.getDomain().isImpure() @@ -2675,6 +2715,7 @@ class AwaitExpr extends @await_expr, Expr { /** Gets the operand of this `await` expression. */ Expr getOperand() { result = this.getChildExpr(0) } + overlay[global] override predicate isImpure() { any() } override ControlFlowNode getFirstControlFlowNode() { @@ -2698,6 +2739,7 @@ class AwaitExpr extends @await_expr, Expr { * ``` */ class FunctionSentExpr extends @function_sent_expr, Expr { + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "FunctionSentExpr" } @@ -2857,6 +2899,7 @@ class DynamicImportExpr extends @dynamic_import, Expr, Import { } /** A literal path expression appearing in a dynamic import. */ +overlay[global] deprecated private class LiteralDynamicImportPath extends PathExpr, ConstantString { LiteralDynamicImportPath() { exists(DynamicImportExpr di | this.getParentExpr*() = di.getSource()) @@ -2919,6 +2962,7 @@ class OptionalChainRoot extends ChainElem { * ``` */ class ImportMetaExpr extends @import_meta_expr, Expr { + overlay[global] override predicate isImpure() { none() } override string getAPrimaryQlClass() { result = "ImportMetaExpr" } diff --git a/javascript/ql/lib/semmle/javascript/Extend.qll b/javascript/ql/lib/semmle/javascript/Extend.qll index d0eeade58928..e59c11d225ee 100644 --- a/javascript/ql/lib/semmle/javascript/Extend.qll +++ b/javascript/ql/lib/semmle/javascript/Extend.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about `extend`-like functions. */ +overlay[local] +module; import javascript @@ -169,6 +171,7 @@ private class FunctionalExtendCallShallow extends ExtendCall { * * Since all object properties are preserved, we model this as a value-preserving step. */ +overlay[global] private class ExtendCallStep extends PreCallGraphStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(ExtendCall extend | @@ -184,6 +187,7 @@ private import semmle.javascript.dataflow.internal.PreCallGraphStep /** * A step through a cloning library, such as `clone` or `fclone`. */ +overlay[global] private class CloneStep extends PreCallGraphStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(DataFlow::CallNode call | diff --git a/javascript/ql/lib/semmle/javascript/Externs.qll b/javascript/ql/lib/semmle/javascript/Externs.qll index a2a2533d8494..f894107528c4 100644 --- a/javascript/ql/lib/semmle/javascript/Externs.qll +++ b/javascript/ql/lib/semmle/javascript/Externs.qll @@ -36,6 +36,8 @@ * Array.prototype.length; * */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Files.qll b/javascript/ql/lib/semmle/javascript/Files.qll index b9274d92ebaa..8cc14ca0492b 100644 --- a/javascript/ql/lib/semmle/javascript/Files.qll +++ b/javascript/ql/lib/semmle/javascript/Files.qll @@ -1,4 +1,6 @@ /** Provides classes for working with files and folders. */ +overlay[local] +module; import javascript private import NodeModuleResolutionImpl @@ -33,12 +35,14 @@ module Folder = Impl::Folder; /** A folder. */ class Folder extends Container, Impl::Folder { /** Gets the file or subfolder in this folder that has the given `name`, if any. */ + overlay[global] Container getChildContainer(string name) { result = this.getAChildContainer() and result.getBaseName() = name } /** Gets the file in this folder that has the given `stem` and `extension`, if any. */ + overlay[global] File getFile(string stem, string extension) { result = this.getAChildContainer() and result.getStem() = stem and @@ -46,6 +50,7 @@ class Folder extends Container, Impl::Folder { } /** Like `getFile` except `d.ts` is treated as a single extension. */ + overlay[global] private File getFileLongExtension(string stem, string extension) { not (stem.matches("%.d") and extension = "ts") and result = this.getFile(stem, extension) @@ -65,6 +70,7 @@ class Folder extends Container, Impl::Folder { * * HTML files will not be found by this method. */ + overlay[global] File getJavaScriptFile(string stem) { result = min(int p, string ext | @@ -78,6 +84,7 @@ class Folder extends Container, Impl::Folder { * Gets an implementation file and/or a typings file from this folder that has the given `stem`. * This could be a single `.ts` file or a pair of `.js` and `.d.ts` files. */ + overlay[global] File getJavaScriptFileOrTypings(string stem) { exists(File jsFile | jsFile = this.getJavaScriptFile(stem) | result = jsFile @@ -88,6 +95,7 @@ class Folder extends Container, Impl::Folder { } /** Gets a subfolder contained in this folder. */ + overlay[global] Folder getASubFolder() { result = this.getAChildContainer() } } diff --git a/javascript/ql/lib/semmle/javascript/Functions.qll b/javascript/ql/lib/semmle/javascript/Functions.qll index b72bfbc888e9..9b1f98c3d0b6 100644 --- a/javascript/ql/lib/semmle/javascript/Functions.qll +++ b/javascript/ql/lib/semmle/javascript/Functions.qll @@ -1,4 +1,6 @@ /** Provides classes for working with functions. */ +overlay[local] +module; import javascript @@ -434,11 +436,13 @@ class Function extends @function, Parameterized, TypeParameterized, StmtContaine * * This predicate is only populated for files extracted with full TypeScript extraction. */ + overlay[global] deprecated CanonicalFunctionName getCanonicalName() { ast_node_symbol(this, result) } /** * Gets the call signature of this function, as determined by the TypeScript compiler, if any. */ + overlay[global] deprecated CallSignatureType getCallSignature() { declared_function_signature(this, result) } } diff --git a/javascript/ql/lib/semmle/javascript/GeneratedCode.qll b/javascript/ql/lib/semmle/javascript/GeneratedCode.qll index e045a98f3b07..8f13a3847307 100644 --- a/javascript/ql/lib/semmle/javascript/GeneratedCode.qll +++ b/javascript/ql/lib/semmle/javascript/GeneratedCode.qll @@ -1,6 +1,8 @@ /** * Provides classes for detecting generated code. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Bundling diff --git a/javascript/ql/lib/semmle/javascript/Generators.qll b/javascript/ql/lib/semmle/javascript/Generators.qll index b2b81ef5c882..f8bf45c577dd 100644 --- a/javascript/ql/lib/semmle/javascript/Generators.qll +++ b/javascript/ql/lib/semmle/javascript/Generators.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with generator functions. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.PreCallGraphStep diff --git a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll index 4a461961f8af..53e5a779a9b5 100644 --- a/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/GlobalAccessPaths.qll @@ -1,6 +1,8 @@ /** * Provides predicates for associating qualified names with data flow nodes. */ +overlay[local] +module; import javascript private import semmle.javascript.dataflow.InferredTypes @@ -204,6 +206,7 @@ module AccessPath { * Holds if the global `accessPath` is only assigned to from one file, not counting * self-assignments. */ + overlay[global] predicate isAssignedInUniqueFile(string accessPath) { strictcount(File f | isAssignedInFile(accessPath, f)) = 1 } @@ -354,6 +357,7 @@ module AccessPath { * Gets a variable that is relevant for the computations in the `GetLaterAccess` module. * This predicate restricts as much as it can, but without depending on `getAVariableRef`. */ + overlay[caller] pragma[inline] private SsaVariable getARelevantVariableSimple() { // The variable might be used where `getLaterBaseAccess()` is called. @@ -405,6 +409,7 @@ module AccessPath { * } * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceTo(Root root, string path) { path = fromReference(result, root) and @@ -428,6 +433,7 @@ module AccessPath { * })(NS = NS || {}); * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceTo(string path) { path = fromReference(result, DataFlow::globalAccessPathRootPseudoNode()) @@ -449,6 +455,7 @@ module AccessPath { * } * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAnAssignmentTo(Root root, string path) { path = fromRhs(result, root) and @@ -470,6 +477,7 @@ module AccessPath { * })(foo = foo || {}); * ``` */ + overlay[caller] pragma[inline] DataFlow::Node getAnAssignmentTo(string path) { path = fromRhs(result, DataFlow::globalAccessPathRootPseudoNode()) @@ -480,6 +488,7 @@ module AccessPath { * * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceOrAssignmentTo(string path) { result = getAReferenceTo(path) @@ -492,6 +501,7 @@ module AccessPath { * * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ + overlay[caller] pragma[inline] DataFlow::Node getAReferenceOrAssignmentTo(Root root, string path) { result = getAReferenceTo(root, path) @@ -502,6 +512,7 @@ module AccessPath { /** * Holds if there is a step from `pred` to `succ` through an assignment to an access path. */ + overlay[caller?] pragma[inline] predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(string name, Root root | @@ -519,6 +530,7 @@ module AccessPath { /** * Gets a `SourceNode` that refers to the same value or access path as the given node. */ + overlay[caller] pragma[inline] DataFlow::SourceNode getAnAliasedSourceNode(DataFlow::Node node) { exists(DataFlow::SourceNode root, string accessPath | @@ -657,7 +669,7 @@ module AccessPath { */ cached predicate hasDominatingWrite(DataFlow::PropRead read) { - Stages::TypeTracking::ref() and + Stages::DataFlowStage::ref() and // within the same basic block. exists(ReachableBasicBlock bb, Root root, string path, int ranking | read.asExpr() = rankedAccessPath(bb, root, path, ranking, AccessPathRead()) and diff --git a/javascript/ql/lib/semmle/javascript/HTML.qll b/javascript/ql/lib/semmle/javascript/HTML.qll index 43b66db459ff..8f70150963ef 100644 --- a/javascript/ql/lib/semmle/javascript/HTML.qll +++ b/javascript/ql/lib/semmle/javascript/HTML.qll @@ -1,4 +1,6 @@ /** Provides classes for working with HTML documents. */ +overlay[local] +module; import javascript @@ -283,6 +285,7 @@ module HTML { /** * A path string arising from the `src` attribute of a `script` tag. */ + overlay[global] deprecated private class ScriptSrcPath extends PathString { ScriptSrcPath() { scriptSrc(this, _) } diff --git a/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll b/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll index c8a0895e6843..fd3b34a1bbd7 100644 --- a/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll +++ b/javascript/ql/lib/semmle/javascript/HtmlSanitizers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with HTML sanitizers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/InclusionTests.qll b/javascript/ql/lib/semmle/javascript/InclusionTests.qll index 3d9921bf6ff2..aa0bd8a2df3e 100644 --- a/javascript/ql/lib/semmle/javascript/InclusionTests.qll +++ b/javascript/ql/lib/semmle/javascript/InclusionTests.qll @@ -1,6 +1,8 @@ /** * Contains classes for recognizing array and string inclusion tests. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/JSDoc.qll b/javascript/ql/lib/semmle/javascript/JSDoc.qll index 85b7695cd70e..f63e24d9c6c0 100644 --- a/javascript/ql/lib/semmle/javascript/JSDoc.qll +++ b/javascript/ql/lib/semmle/javascript/JSDoc.qll @@ -1,4 +1,6 @@ /** Provides classes for working with JSDoc comments. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -627,6 +629,7 @@ module JSDoc { /** * A statement container which may declare JSDoc name aliases. */ + overlay[global] deprecated class Environment extends StmtContainer { /** * Gets the fully qualified name aliased by the given unqualified name diff --git a/javascript/ql/lib/semmle/javascript/JSON.qll b/javascript/ql/lib/semmle/javascript/JSON.qll index 19fc3ec84d7a..ca322bacd467 100644 --- a/javascript/ql/lib/semmle/javascript/JSON.qll +++ b/javascript/ql/lib/semmle/javascript/JSON.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSON data. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/JSX.qll b/javascript/ql/lib/semmle/javascript/JSX.qll index ed8a7b097a6b..d182f1553543 100644 --- a/javascript/ql/lib/semmle/javascript/JSX.qll +++ b/javascript/ql/lib/semmle/javascript/JSX.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSX code. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/JsonParsers.qll b/javascript/ql/lib/semmle/javascript/JsonParsers.qll index f447f0e41c9e..cf7a06ef09ce 100644 --- a/javascript/ql/lib/semmle/javascript/JsonParsers.qll +++ b/javascript/ql/lib/semmle/javascript/JsonParsers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSON parsers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/JsonSchema.qll b/javascript/ql/lib/semmle/javascript/JsonSchema.qll index a298abfd2dd7..dd7c50875578 100644 --- a/javascript/ql/lib/semmle/javascript/JsonSchema.qll +++ b/javascript/ql/lib/semmle/javascript/JsonSchema.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with JSON schema libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll index bb1b23610c94..d36911b299c0 100644 --- a/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll +++ b/javascript/ql/lib/semmle/javascript/JsonStringifiers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSON serializers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Lines.qll b/javascript/ql/lib/semmle/javascript/Lines.qll index 1db9187008a1..272be691498b 100644 --- a/javascript/ql/lib/semmle/javascript/Lines.qll +++ b/javascript/ql/lib/semmle/javascript/Lines.qll @@ -4,6 +4,8 @@ * This information is only available for snapshots that have been extracted with * the `--extract-program-text` flag. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Locations.qll b/javascript/ql/lib/semmle/javascript/Locations.qll index a3ad79ef93ea..1c48a3adbd3f 100644 --- a/javascript/ql/lib/semmle/javascript/Locations.qll +++ b/javascript/ql/lib/semmle/javascript/Locations.qll @@ -1,4 +1,6 @@ /** Provides classes for working with locations and program elements that have locations. */ +overlay[local] +module; import javascript @@ -30,6 +32,7 @@ final class Location extends @location_default { int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 } /** Holds if this location starts before location `that`. */ + overlay[caller] pragma[inline] predicate startsBefore(Location that) { exists(string f, int sl1, int sc1, int sl2, int sc2 | @@ -43,6 +46,7 @@ final class Location extends @location_default { } /** Holds if this location ends after location `that`. */ + overlay[caller] pragma[inline] predicate endsAfter(Location that) { exists(string f, int el1, int ec1, int el2, int ec2 | diff --git a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll index b294cb7ca3ab..e7a89ebb32ae 100644 --- a/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll +++ b/javascript/ql/lib/semmle/javascript/MembershipCandidates.qll @@ -1,6 +1,8 @@ /** * Provides classes for recognizing membership tests. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Modules.qll b/javascript/ql/lib/semmle/javascript/Modules.qll index 8b0330b708ba..bc69695121e7 100644 --- a/javascript/ql/lib/semmle/javascript/Modules.qll +++ b/javascript/ql/lib/semmle/javascript/Modules.qll @@ -3,6 +3,8 @@ * ECMAScript 2015-style modules, and the older CommonJS and AMD-style * modules. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages @@ -23,9 +25,11 @@ abstract class Module extends TopLevel { Import getAnImport() { result.getTopLevel() = this } /** Gets a module from which this module imports. */ + overlay[global] Module getAnImportedModule() { result = this.getAnImport().getImportedModule() } /** Gets a symbol exported by this module. */ + overlay[global] string getAnExportedSymbol() { exists(this.getAnExportedValue(result)) } /** @@ -39,12 +43,14 @@ abstract class Module extends TopLevel { * Symbols defined in another module that are re-exported by * this module are only sometimes considered. */ + overlay[global] cached abstract DataFlow::Node getAnExportedValue(string name); /** * Gets a value that is exported as the whole exports object of this module. */ + overlay[global] cached DataFlow::Node getABulkExportedNode() { none() } // overridden in subclasses @@ -55,6 +61,7 @@ abstract class Module extends TopLevel { * This can be used to determine which value a default-import will likely refer to, * as the interaction between different module types is not standardized. */ + overlay[global] DataFlow::Node getDefaultOrBulkExport() { result = [this.getAnExportedValue("default"), this.getABulkExportedNode()] } @@ -69,6 +76,7 @@ abstract class Module extends TopLevel { * This predicate is not part of the public API, it is only exposed to allow * overriding by subclasses. */ + overlay[global] deprecated predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { path.getEnclosingModule() = this and priority = 0 and @@ -90,6 +98,7 @@ abstract class Module extends TopLevel { * resolves to a folder containing a main module (such as `index.js`), then * that file is the result. */ + overlay[global] deprecated File resolve(PathExpr path) { path.getEnclosingModule() = this and ( @@ -124,6 +133,7 @@ abstract class Import extends AstNode { abstract Module getEnclosingModule(); /** DEPRECATED. Use `getImportedPathExpr` instead. */ + overlay[global] deprecated PathExpr getImportedPath() { result = this.getImportedPathExpr() } /** Gets the (unresolved) path that this import refers to. */ @@ -138,6 +148,7 @@ abstract class Import extends AstNode { * Any externs module whose name exactly matches the imported * path is assumed to be a possible target of the import. */ + overlay[global] Module resolveExternsImport() { result.isExterns() and result.getName() = this.getImportedPathString() } @@ -145,16 +156,19 @@ abstract class Import extends AstNode { /** * Gets the module the path of this import resolves to. */ + overlay[global] Module resolveImportedPath() { result.getFile() = this.getImportedFile() } /** * Gets the module the path of this import resolves to. */ + overlay[global] File getImportedFile() { result = ImportPathResolver::resolveExpr(this.getImportedPathExpr()) } /** * DEPRECATED. Use `getImportedModule()` instead. */ + overlay[global] deprecated Module resolveFromTypeScriptSymbol() { exists(CanonicalName symbol | ast_node_symbol(this, symbol) and @@ -170,6 +184,7 @@ abstract class Import extends AstNode { * behavior of Node.js imports, which prefer core modules such as `fs` over any * source module of the same name. */ + overlay[global] cached Module getImportedModule() { Stages::Imports::ref() and @@ -210,6 +225,7 @@ abstract class Import extends AstNode { * in cases where it would cause ambiguity between named exports and properties * of a default export. */ + overlay[global] final DataFlow::Node getImportedModuleNodeStrict() { result = this.getImportedModuleNode() and not ( diff --git a/javascript/ql/lib/semmle/javascript/NPM.qll b/javascript/ql/lib/semmle/javascript/NPM.qll index cbe580b45689..857fc1638047 100644 --- a/javascript/ql/lib/semmle/javascript/NPM.qll +++ b/javascript/ql/lib/semmle/javascript/NPM.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with NPM module definitions and dependencies. */ +overlay[local?] +module; import javascript private import NodeModuleResolutionImpl diff --git a/javascript/ql/lib/semmle/javascript/NodeJS.qll b/javascript/ql/lib/semmle/javascript/NodeJS.qll index 7e9e2fdea904..dfc2dd15ad36 100644 --- a/javascript/ql/lib/semmle/javascript/NodeJS.qll +++ b/javascript/ql/lib/semmle/javascript/NodeJS.qll @@ -17,6 +17,7 @@ private import semmle.javascript.dataflow.internal.DataFlowNode * process.stdout.write(fs.readFileSync(process.argv[i], 'utf8')); * ``` */ +overlay[local] class NodeModule extends Module { NodeModule() { is_module(this) and @@ -36,11 +37,13 @@ class NodeModule extends Module { * Gets an abstract value representing one or more values that may flow * into this module's `module.exports` property. */ + overlay[global] pragma[noinline] DefiniteAbstractValue getAModuleExportsValue() { result = this.getAModuleExportsProperty().getAValue() } + overlay[global] pragma[noinline] private AbstractProperty getAModuleExportsProperty() { result.getBase().(AbstractModuleObject).getModule() = this and @@ -52,12 +55,14 @@ class NodeModule extends Module { * For performance this predicate only computes relevant expressions (in `getAModuleExportsCandidate`). * So if using this predicate - consider expanding the list of relevant expressions. */ + overlay[global] DataFlow::AnalyzedNode getAModuleExportsNode() { result = getAModuleExportsCandidate() and result.getAValue() = this.getAModuleExportsValue() } /** Gets a symbol exported by this module. */ + overlay[global] override string getAnExportedSymbol() { result = super.getAnExportedSymbol() or @@ -70,6 +75,7 @@ class NodeModule extends Module { ) } + overlay[global] override DataFlow::Node getAnExportedValue(string name) { // a property write whose base is `exports` or `module.exports` exists(DataFlow::PropWrite pwn | result = pwn.getRhs() | @@ -114,6 +120,7 @@ class NodeModule extends Module { ) } + overlay[global] override DataFlow::Node getABulkExportedNode() { Stages::Imports::ref() and exists(DataFlow::PropWrite write | @@ -124,6 +131,7 @@ class NodeModule extends Module { } /** Gets a symbol that the module object inherits from its prototypes. */ + overlay[global] private string getAnImplicitlyExportedSymbol() { exists(ExternalConstructor ec | ec = this.getPrototypeOfExportedExpr() | result = ec.getAMember().getName() @@ -136,6 +144,7 @@ class NodeModule extends Module { } /** Gets an externs declaration of the prototype object of a value exported by this module. */ + overlay[global] private ExternalConstructor getPrototypeOfExportedExpr() { exists(AbstractValue exported | exported = this.getAModuleExportsValue() | result instanceof ObjectExternal @@ -146,6 +155,7 @@ class NodeModule extends Module { ) } + overlay[global] deprecated override predicate searchRoot(PathExpr path, Folder searchRoot, int priority) { path.getEnclosingModule() = this and exists(string pathval | pathval = path.getValue() | @@ -224,6 +234,7 @@ predicate findNodeModulesFolder(Folder f, Folder nodeModules, int distance) { /** * A Node.js `require` variable. */ +overlay[local] private class RequireVariable extends Variable { RequireVariable() { this = any(ModuleScope m).getVariable("require") @@ -236,6 +247,7 @@ private class RequireVariable extends Variable { } } +overlay[local] private predicate isModuleModule(EarlyStageNode nd) { exists(ImportDeclaration imp | imp.getRawImportPath() = "module" | nd = TDestructuredModuleImportNode(imp) @@ -249,6 +261,7 @@ private predicate isModuleModule(EarlyStageNode nd) { ) } +overlay[local] private predicate isCreateRequire(EarlyStageNode nd) { exists(PropAccess prop | isModuleModule(TValueNode(prop.getBase())) and @@ -278,6 +291,7 @@ private predicate isCreateRequire(EarlyStageNode nd) { /** * Holds if `nd` may refer to `require`, either directly or modulo local data flow. */ +overlay[local] cached private predicate isRequire(EarlyStageNode nd) { exists(VarAccess access | @@ -320,6 +334,7 @@ private predicate isRequire(EarlyStageNode nd) { * require('fs') * ``` */ +overlay[local] class Require extends CallExpr, Import { Require() { isRequire(TValueNode(this.getCallee())) } diff --git a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll index 467e14aa74fb..ac94c153baa3 100644 --- a/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll +++ b/javascript/ql/lib/semmle/javascript/NodeModuleResolutionImpl.qll @@ -3,6 +3,8 @@ * * Provides predicates for modeling Node.js module resolution. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/PackageExports.qll b/javascript/ql/lib/semmle/javascript/PackageExports.qll index b4032980688f..56c2366b8246 100644 --- a/javascript/ql/lib/semmle/javascript/PackageExports.qll +++ b/javascript/ql/lib/semmle/javascript/PackageExports.qll @@ -3,6 +3,8 @@ * * Provides predicates for working with values exported from a package. */ +overlay[local?] +module; import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/Paths.qll b/javascript/ql/lib/semmle/javascript/Paths.qll index 38c24a1b8e90..1a98c477f575 100644 --- a/javascript/ql/lib/semmle/javascript/Paths.qll +++ b/javascript/ql/lib/semmle/javascript/Paths.qll @@ -2,6 +2,8 @@ * Provides classes for working with file system paths and program expressions * that denote them. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/PrintAst.qll b/javascript/ql/lib/semmle/javascript/PrintAst.qll index b4f40d99f235..7bc79c5509e5 100644 --- a/javascript/ql/lib/semmle/javascript/PrintAst.qll +++ b/javascript/ql/lib/semmle/javascript/PrintAst.qll @@ -5,6 +5,8 @@ * extend `PrintAstConfiguration` and override `shouldPrint` to hold for only the elements * you wish to view the AST for. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Promises.qll b/javascript/ql/lib/semmle/javascript/Promises.qll index 2feb92e2e553..f373ca87d39a 100644 --- a/javascript/ql/lib/semmle/javascript/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/Promises.qll @@ -186,11 +186,13 @@ module Promises { /** * Gets the pseudo-field used to describe resolved values in a promise. */ + overlay[local] string valueProp() { result = "$PromiseResolveField$" } /** * Gets the pseudo-field used to describe rejected values in a promise. */ + overlay[local] string errorProp() { result = "$PromiseRejectField$" } /** A property set containing the pseudo-properites of a promise object. */ @@ -236,6 +238,7 @@ module PromiseTypeTracking { * * These type-tracking steps are already included in the default type-tracking steps (through `PreCallGraphStep`). */ + overlay[caller?] pragma[inline] DataFlow::Node promiseStep(DataFlow::Node pred, StepSummary summary) { exists(string field | field = Promises::valueProp() | @@ -254,6 +257,7 @@ module PromiseTypeTracking { * Gets the result from a single step through a promise, from `pred` with tracker `t2` to `result` with tracker `t`. * This can be loading a resolved value from a promise, storing a value in a promise, or copying a resolved value from one promise to another. */ + overlay[caller?] pragma[inline] DataFlow::SourceNode promiseStep( DataFlow::SourceNode pred, DataFlow::TypeTracker t, DataFlow::TypeTracker t2 diff --git a/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll b/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll index a385df662ce2..e0713f4f31b1 100644 --- a/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll +++ b/javascript/ql/lib/semmle/javascript/RangeAnalysis.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript /* diff --git a/javascript/ql/lib/semmle/javascript/Regexp.qll b/javascript/ql/lib/semmle/javascript/Regexp.qll index ea2993ae7da8..db779e600d67 100644 --- a/javascript/ql/lib/semmle/javascript/Regexp.qll +++ b/javascript/ql/lib/semmle/javascript/Regexp.qll @@ -4,6 +4,8 @@ * Regular expression literals are represented as an abstract syntax tree of regular expression * terms. */ +overlay[local] +module; import javascript private import semmle.javascript.dataflow.InferredTypes @@ -150,6 +152,7 @@ class RegExpTerm extends Locatable, @regexpterm { * /[a-z]+/g; // YES - Regexp literals are always used as regexp * ``` */ + overlay[global] predicate isUsedAsRegExp() { exists(RegExpParent parent | parent = this.getRootTerm().getParent() | parent instanceof RegExpLiteral @@ -964,6 +967,7 @@ class RegExpParseError extends Error, @regexp_parse_error { /** * Holds if `func` is a method defined on `String.prototype` with name `name`. */ +overlay[global] private predicate isNativeStringMethod(Function func, string name) { exists(ExternalInstanceMemberDecl decl | decl.hasQualifiedName("String", name) and @@ -975,6 +979,7 @@ private predicate isNativeStringMethod(Function func, string name) { * Holds if `name` is the name of a property on a Match object returned by `String.prototype.match`, * not including array indices. */ +overlay[global] private predicate isMatchObjectProperty(string name) { any(ExternalInstanceMemberDecl decl).hasQualifiedName("Array", name) or @@ -982,6 +987,7 @@ private predicate isMatchObjectProperty(string name) { } /** Holds if `call` is a call to `match` whose result is used in a way that is incompatible with Match objects. */ +overlay[global] private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) { call.getMethodName() = ["match", "matchAll"] and call.getNumArgument() = 1 and @@ -1006,10 +1012,11 @@ private predicate isUsedAsNonMatchObject(DataFlow::MethodCallNode call) { /** * Holds if `value` is used in a way that suggests it returns a number. */ +overlay[global] pragma[inline] private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) { any(Comparison compare) - .hasOperands(value.getALocalUse().asExpr(), any(Expr e | e.analyze().getAType() = TTNumber())) + .hasOperands(value.getALocalUse().asExpr(), any(Expr e | canBeNumber(e.analyze()))) or value.flowsToExpr(any(ArithmeticExpr e).getAnOperand()) or @@ -1024,20 +1031,31 @@ private predicate isUsedAsNumber(DataFlow::LocalSourceNode value) { ) } +bindingset[node] +overlay[global] +pragma[inline_late] +private predicate canBeString(DataFlow::AnalyzedNode node) { node.getAType() = TTString() } + +bindingset[node] +overlay[global] +pragma[inline_late] +private predicate canBeNumber(DataFlow::AnalyzedNode node) { node.getAType() = TTNumber() } + /** * Holds if `source` may be interpreted as a regular expression. */ +overlay[global] cached predicate isInterpretedAsRegExp(DataFlow::Node source) { Stages::Taint::ref() and - source.analyze().getAType() = TTString() and + canBeString(source) and ( // The first argument to an invocation of `RegExp` (with or without `new`). source = DataFlow::globalVarRef("RegExp").getAnInvocation().getArgument(0) or // The argument of a call that coerces the argument to a regular expression. exists(DataFlow::MethodCallNode mce, string methodName | - mce.getReceiver().analyze().getAType() = TTString() and + canBeString(mce.getReceiver()) and mce.getMethodName() = methodName and not exists(Function func | func = mce.getACallee() | not isNativeStringMethod(func, methodName) @@ -1073,6 +1091,7 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) { * Gets a node whose value may flow (inter-procedurally) to `re`, where it is interpreted * as a part of a regular expression. */ +overlay[global] private DataFlow::Node regExpSource(DataFlow::Node re, DataFlow::TypeBackTracker t) { t.start() and re = result and @@ -1090,6 +1109,7 @@ private DataFlow::Node regExpSource(DataFlow::Node re, DataFlow::TypeBackTracker * Gets a node whose value may flow (inter-procedurally) to `re`, where it is interpreted * as a part of a regular expression. */ +overlay[global] private DataFlow::Node regExpSource(DataFlow::Node re) { result = regExpSource(re, DataFlow::TypeBackTracker::end()) } @@ -1098,6 +1118,7 @@ private DataFlow::Node regExpSource(DataFlow::Node re) { * A node whose value may flow to a position where it is interpreted * as a part of a regular expression. */ +overlay[global] abstract class RegExpPatternSource extends DataFlow::Node { /** * Gets a node where the pattern of this node is parsed as a part of @@ -1126,6 +1147,7 @@ abstract class RegExpPatternSource extends DataFlow::Node { /** * A regular expression literal, viewed as the pattern source for itself. */ +overlay[global] private class RegExpLiteralPatternSource extends RegExpPatternSource, DataFlow::ValueNode { override RegExpLiteral astNode; @@ -1145,6 +1167,7 @@ private class RegExpLiteralPatternSource extends RegExpPatternSource, DataFlow:: * A node whose string value may flow to a position where it is interpreted * as a part of a regular expression. */ +overlay[global] private class StringRegExpPatternSource extends RegExpPatternSource { DataFlow::Node parse; @@ -1169,6 +1192,7 @@ private class StringRegExpPatternSource extends RegExpPatternSource { * A node whose string value may flow to a position where it is interpreted * as a part of a regular expression. */ +overlay[global] private class StringConcatRegExpPatternSource extends RegExpPatternSource { DataFlow::Node parse; @@ -1331,6 +1355,7 @@ module RegExp { /** * Gets the AST of a regular expression object that can flow to `node`. */ + overlay[global] RegExpTerm getRegExpObjectFromNode(DataFlow::Node node) { exists(DataFlow::RegExpCreationNode regexp | regexp.getAReference().flowsTo(node) and @@ -1342,6 +1367,7 @@ module RegExp { * Gets the AST of a regular expression that can flow to `node`, * including `RegExp` objects as well as strings interpreted as regular expressions. */ + overlay[global] RegExpTerm getRegExpFromNode(DataFlow::Node node) { result = getRegExpObjectFromNode(node) or diff --git a/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll b/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll index 47ee41a42357..2276f496813a 100644 --- a/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll +++ b/javascript/ql/lib/semmle/javascript/RestrictedLocations.qll @@ -1,4 +1,6 @@ /** Provides classes for restricting the locations reported for program elements. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Routing.qll b/javascript/ql/lib/semmle/javascript/Routing.qll index 8fe9f79d8623..2b051b9c6894 100644 --- a/javascript/ql/lib/semmle/javascript/Routing.qll +++ b/javascript/ql/lib/semmle/javascript/Routing.qll @@ -2,6 +2,8 @@ * A model of routing trees, describing the composition of route handlers and middleware functions * in a web server application. See `Routing::Node` for more details. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps @@ -279,6 +281,7 @@ module Routing { /** * Holds if `node` has processed the incoming request strictly prior to this node. */ + overlay[caller?] pragma[inline] predicate isGuardedByNode(Node node) { this.isGuardedByNodeInternal(pragma[only_bind_out](node)) @@ -287,6 +290,7 @@ module Routing { /** * Holds if the middleware corresponding to `node` has processed the incoming request strictly prior to this node. */ + overlay[caller?] pragma[inline] predicate isGuardedBy(DataFlow::Node node) { this.isGuardedByNode(getNode(node)) } @@ -894,6 +898,7 @@ module Routing { * Gets a node that is stored in the given access path on this route handler parameter, either * during execution of this router handler, or in one of the preceding ones. */ + overlay[caller?] pragma[inline] DataFlow::Node getValueFromAccessPath(string path) { exists(int i, Node predecessor | diff --git a/javascript/ql/lib/semmle/javascript/SSA.qll b/javascript/ql/lib/semmle/javascript/SSA.qll index a2c5bf1d34e6..52486a7b7e3b 100644 --- a/javascript/ql/lib/semmle/javascript/SSA.qll +++ b/javascript/ql/lib/semmle/javascript/SSA.qll @@ -73,6 +73,8 @@ * expression in `k` induces a re-capture of `x` to reflect the fact that `x` * is incremented between the two `console.log` calls. */ +overlay[local] +module; import javascript private import semmle.javascript.dataflow.Refinements diff --git a/javascript/ql/lib/semmle/javascript/SourceMaps.qll b/javascript/ql/lib/semmle/javascript/SourceMaps.qll index 21fa71121324..e64e3db2b39f 100644 --- a/javascript/ql/lib/semmle/javascript/SourceMaps.qll +++ b/javascript/ql/lib/semmle/javascript/SourceMaps.qll @@ -1,4 +1,6 @@ /** Provides a class for representing source maps. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll index 5104469635d7..c72fc0d8f8ba 100644 --- a/javascript/ql/lib/semmle/javascript/StandardLibrary.qll +++ b/javascript/ql/lib/semmle/javascript/StandardLibrary.qll @@ -1,4 +1,6 @@ /** Provides classes for working with standard library objects. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Stmt.qll b/javascript/ql/lib/semmle/javascript/Stmt.qll index 93eb1d1dea07..f97b07ac8e94 100644 --- a/javascript/ql/lib/semmle/javascript/Stmt.qll +++ b/javascript/ql/lib/semmle/javascript/Stmt.qll @@ -1,4 +1,6 @@ /** Provides classes for working with statements. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/StringConcatenation.qll b/javascript/ql/lib/semmle/javascript/StringConcatenation.qll index d4039cbf41a4..ca6485cc5b4e 100644 --- a/javascript/ql/lib/semmle/javascript/StringConcatenation.qll +++ b/javascript/ql/lib/semmle/javascript/StringConcatenation.qll @@ -1,6 +1,8 @@ /** * Provides predicates for analyzing string concatenations and their operands. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/StringOps.qll b/javascript/ql/lib/semmle/javascript/StringOps.qll index f2b7f3eb9aa7..6c7bb721b1ad 100644 --- a/javascript/ql/lib/semmle/javascript/StringOps.qll +++ b/javascript/ql/lib/semmle/javascript/StringOps.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about string-manipulating expressions. */ +overlay[local?] +module; import javascript @@ -387,6 +389,7 @@ module StringOps { * ``` */ class ConcatenationNode extends DataFlow::Node { + overlay[caller?] pragma[inline] ConcatenationNode() { exists(StringConcatenation::getAnOperand(this)) @@ -397,36 +400,42 @@ module StringOps { /** * Gets the `n`th operand of this string concatenation. */ + overlay[caller?] pragma[inline] ConcatenationOperand getOperand(int n) { result = StringConcatenation::getOperand(this, n) } /** * Gets an operand of this string concatenation. */ + overlay[caller?] pragma[inline] ConcatenationOperand getAnOperand() { result = StringConcatenation::getAnOperand(this) } /** * Gets the number of operands of this string concatenation. */ + overlay[caller?] pragma[inline] int getNumOperand() { result = StringConcatenation::getNumOperand(this) } /** * Gets the first operand of this string concatenation. */ + overlay[caller?] pragma[inline] ConcatenationOperand getFirstOperand() { result = StringConcatenation::getFirstOperand(this) } /** * Gets the last operand of this string concatenation */ + overlay[caller?] pragma[inline] ConcatenationOperand getLastOperand() { result = StringConcatenation::getLastOperand(this) } /** * Holds if this only acts as a string coercion, such as `"" + x`. */ + overlay[caller?] pragma[inline] predicate isCoercion() { StringConcatenation::isCoercion(this) } @@ -435,6 +444,7 @@ module StringOps { * it is a concatenation operator that is not itself the immediate operand to * another concatenation operator. */ + overlay[caller?] pragma[inline] predicate isRoot() { StringConcatenation::isRoot(this) } @@ -442,18 +452,21 @@ module StringOps { * Holds if this is a leaf in the concatenation tree, that is, it is not * itself a concatenation. */ + overlay[caller?] pragma[inline] predicate isLeaf() { not exists(StringConcatenation::getAnOperand(this)) } /** * Gets the root of the concatenation tree in which this is an operator. */ + overlay[caller?] pragma[inline] ConcatenationRoot getRoot() { result = StringConcatenation::getRoot(this) } /** * Gets the enclosing concatenation in which this is an operand, if any. */ + overlay[caller?] pragma[inline] Concatenation getParentConcatenation() { this = StringConcatenation::getAnOperand(result) } @@ -462,6 +475,7 @@ module StringOps { * * For example, `z` is the last leaf in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getLastLeaf() { result = StringConcatenation::getLastOperand*(this) } @@ -470,6 +484,7 @@ module StringOps { * * For example, `x` is the first leaf in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getFirstLeaf() { result = StringConcatenation::getFirstOperand*(this) } @@ -479,6 +494,7 @@ module StringOps { * * For example, `y` is the previous leaf from `z` in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getPreviousLeaf() { adjacentLeaves(result, this) } @@ -488,6 +504,7 @@ module StringOps { * * For example, `y` is the next leaf from `x` in `x + y + z`. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getNextLeaf() { adjacentLeaves(this, result) } } @@ -507,6 +524,7 @@ module StringOps { * See `ConcatenationNode` for more information. */ class Concatenation extends ConcatenationNode { + overlay[caller?] pragma[inline] Concatenation() { exists(StringConcatenation::getAnOperand(this)) } } @@ -524,6 +542,7 @@ module StringOps { * See `ConcatenationNode` for more information. */ class ConcatenationOperand extends ConcatenationNode { + overlay[caller?] pragma[inline] ConcatenationOperand() { this = StringConcatenation::getAnOperand(_) } } @@ -541,12 +560,14 @@ module StringOps { * See `ConcatenationNode` for more information. */ class ConcatenationRoot extends Concatenation { + overlay[caller?] pragma[inline] ConcatenationRoot() { this.isRoot() } /** * Gets a leaf in this concatenation tree that this node is the root of. */ + overlay[caller?] pragma[inline] ConcatenationLeaf getALeaf() { this = StringConcatenation::getRoot(result) } @@ -606,6 +627,7 @@ module StringOps { * See `ConcatenationNode` for more information. */ class ConcatenationLeaf extends ConcatenationOperand { + overlay[caller?] pragma[inline] ConcatenationLeaf() { this.isLeaf() } } diff --git a/javascript/ql/lib/semmle/javascript/TSConfig.qll b/javascript/ql/lib/semmle/javascript/TSConfig.qll index c10177e5fe24..2d5c2e6ae919 100644 --- a/javascript/ql/lib/semmle/javascript/TSConfig.qll +++ b/javascript/ql/lib/semmle/javascript/TSConfig.qll @@ -1,6 +1,8 @@ /** * Provides a class for working with `tsconfig.json` files. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.paths.PathMapping diff --git a/javascript/ql/lib/semmle/javascript/Templates.qll b/javascript/ql/lib/semmle/javascript/Templates.qll index 5e2b4a2d8aae..1b3db059226b 100644 --- a/javascript/ql/lib/semmle/javascript/Templates.qll +++ b/javascript/ql/lib/semmle/javascript/Templates.qll @@ -1,4 +1,6 @@ /** Provides classes for working with ECMAScript 2015-style template expressions. */ +overlay[local] +module; import javascript @@ -58,6 +60,7 @@ class TemplateLiteral extends Expr, @template_literal { */ int getNumElement() { result = count(this.getAnElement()) } + overlay[global] override predicate isImpure() { this.getAnElement().isImpure() } override string getAPrimaryQlClass() { result = "TemplateLiteral" } diff --git a/javascript/ql/lib/semmle/javascript/Tokens.qll b/javascript/ql/lib/semmle/javascript/Tokens.qll index c9eeef69dfba..4e1c63440b5b 100644 --- a/javascript/ql/lib/semmle/javascript/Tokens.qll +++ b/javascript/ql/lib/semmle/javascript/Tokens.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with the token-based representation of JavaScript programs. */ +overlay[local] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll b/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll index 6d0a13c4a38f..50201363bea1 100644 --- a/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll +++ b/javascript/ql/lib/semmle/javascript/TypeAnnotations.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about type annotations independently of dialect. */ +overlay[local] +module; import javascript private import internal.StmtContainers @@ -18,6 +20,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * This can be used to map a type name to the class/interface it refers to, or * associate it with a named type coming from an dependency. */ + overlay[global] TypeNameBindingNode getTypeBinding() { result = this } /** Holds if this is the `any` type. */ @@ -90,6 +93,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * Holds if this is a reference to the type with qualified name `globalName` relative to the global scope. */ + overlay[global] deprecated predicate hasQualifiedName(string globalName) { UnderlyingTypes::nodeHasUnderlyingType(this, globalName) } @@ -99,6 +103,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * Holds if this is a reference to the type exported from `moduleName` under the name `exportedName`. */ + overlay[global] deprecated predicate hasQualifiedName(string moduleName, string exportedName) { UnderlyingTypes::nodeHasUnderlyingType(this, moduleName, exportedName) } @@ -107,6 +112,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * Holds if this is a reference to the type with qualified name `globalName` relative to the global scope, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] final predicate hasUnderlyingType(string globalName) { UnderlyingTypes::nodeHasUnderlyingType(this, globalName) } @@ -115,6 +121,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * Holds if this is a reference to the type exported from `moduleName` under the name `exportedName`, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] final predicate hasUnderlyingType(string moduleName, string exportedName) { UnderlyingTypes::nodeHasUnderlyingType(this, moduleName, exportedName) } @@ -135,6 +142,7 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * Note that this has no result for JSDoc type annotations. */ + overlay[global] deprecated Type getType() { none() } /** @@ -142,5 +150,6 @@ class TypeAnnotation extends @type_annotation, NodeInStmtContainer { * * This unfolds nullability modifiers and generic type applications. */ + overlay[global] final DataFlow::ClassNode getClass() { UnderlyingTypes::nodeHasUnderlyingClassType(this, result) } } diff --git a/javascript/ql/lib/semmle/javascript/TypeScript.qll b/javascript/ql/lib/semmle/javascript/TypeScript.qll index 79b71fcd8c05..b9d6ea0af983 100644 --- a/javascript/ql/lib/semmle/javascript/TypeScript.qll +++ b/javascript/ql/lib/semmle/javascript/TypeScript.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + import javascript /** @@ -31,6 +34,7 @@ class NamespaceDefinition extends Stmt, @namespace_definition, AST::ValueNode { /** * Gets the canonical name of the namespace being defined. */ + overlay[global] deprecated Namespace getNamespace() { result.getADefinition() = this } } @@ -111,11 +115,13 @@ class TypeDefinition extends AstNode, @type_definition { /** * Gets the canonical name of the type being defined. */ + overlay[global] deprecated TypeName getTypeName() { result.getADefinition() = this } /** * Gets the type defined by this declaration. */ + overlay[global] deprecated Type getType() { ast_node_type(this.getIdentifier(), result) } override string getAPrimaryQlClass() { result = "TypeDefinition" } @@ -221,6 +227,7 @@ class ExternalModuleReference extends Expr, Import, @external_module_reference { } /** A literal path expression appearing in an external module reference. */ +overlay[global] deprecated private class LiteralExternalModulePath extends PathExpr, ConstantString { LiteralExternalModulePath() { exists(ExternalModuleReference emr | this.getParentExpr*() = emr.getExpression()) @@ -268,6 +275,7 @@ class TypeAliasDeclaration extends @type_alias_declaration, TypeParameterized, S /** * Gets the canonical name of the type being defined. */ + overlay[global] deprecated TypeName getTypeName() { result.getADefinition() = this } override string getAPrimaryQlClass() { result = "TypeAliasDeclaration" } @@ -548,6 +556,7 @@ class LocalNamespaceName extends @local_namespace_name, LexicalName { /** * Gets the canonical name of the namespace referenced by this name. */ + overlay[global] deprecated Namespace getNamespace() { result = this.getADeclaration().getNamespace() } override DeclarationSpace getDeclarationSpace() { result = "namespace" } @@ -568,6 +577,7 @@ class TypeExpr extends ExprOrType, @typeexpr, TypeAnnotation { * Has no result if this occurs in a TypeScript file that was extracted * without type information. */ + overlay[global] deprecated override Type getType() { ast_node_type(this, result) } override Stmt getEnclosingStmt() { result = ExprOrType.super.getEnclosingStmt() } @@ -692,6 +702,7 @@ class TypeAccess extends @typeaccess, TypeExpr, TypeRef { /** * Gets the canonical name of the type being accessed. */ + overlay[global] deprecated TypeName getTypeName() { ast_node_symbol(this, result) } override string getAPrimaryQlClass() { result = "TypeAccess" } @@ -1379,6 +1390,7 @@ class LocalNamespaceDecl extends VarDecl, NamespaceRef { /** * Gets the canonical name of the namespace being defined or aliased by this name. */ + overlay[global] deprecated Namespace getNamespace() { ast_node_symbol(this, result) } } @@ -1397,6 +1409,7 @@ class NamespaceAccess extends TypeExpr, NamespaceRef, @namespace_access { /** * Gets the canonical name of the namespace being accessed. */ + overlay[global] deprecated Namespace getNamespace() { ast_node_symbol(this, result) } override string getAPrimaryQlClass() { result = "NamespaceAccess" } @@ -1506,6 +1519,7 @@ class EnumDeclaration extends NamespaceDefinition, @enum_declaration, AST::Value /** * Gets the canonical name of the type being defined. */ + overlay[global] deprecated TypeName getTypeName() { ast_node_symbol(this, result) } /** @@ -1594,6 +1608,7 @@ class EnumMember extends AstNode, @enum_member { /** * Gets the canonical name of the type defined by this enum member. */ + overlay[global] deprecated TypeName getTypeName() { ast_node_symbol(this, result) } override string getAPrimaryQlClass() { result = "EnumMember" } @@ -1762,6 +1777,7 @@ class TypeRootFolder extends Folder { /** * Gets the priority with which this type root folder should be used from within the given search root. */ + overlay[global] int getSearchPriority(Folder searchRoot) { findNodeModulesFolder(searchRoot, this.getNodeModulesFolder(), result) } @@ -1780,6 +1796,7 @@ class TypeRootFolder extends Folder { * For instance, there may be many AST nodes representing different uses of the * `number` keyword, but there only exists one `number` type. */ +overlay[global] deprecated class Type extends @type { /** * Gets a string representation of this type. @@ -1984,6 +2001,7 @@ deprecated class Type extends @type { * * A union type or intersection type, such as `string | number` or `T & U`. */ +overlay[global] deprecated class UnionOrIntersectionType extends Type, @union_or_intersection_type { /** * Gets the `i`th member of this union or intersection, starting at 0. @@ -2012,6 +2030,7 @@ deprecated class UnionOrIntersectionType extends Type, @union_or_intersection_ty * Note that the `boolean` type is represented as the union `true | false`, * but is still displayed as `boolean` in string representations. */ +overlay[global] deprecated class UnionType extends UnionOrIntersectionType, @union_type { } /** @@ -2022,6 +2041,7 @@ deprecated class UnionType extends UnionOrIntersectionType, @union_type { } * * An intersection type, such as `T & {x: number}`. */ +overlay[global] deprecated class IntersectionType extends UnionOrIntersectionType, @intersection_type { } /** @@ -2040,6 +2060,7 @@ deprecated class IntersectionType extends UnionOrIntersectionType, @intersection * Foreign array-like objects such as `HTMLCollection` are not normal JavaScript arrays, * and their corresponding types are not considered array types either. */ +overlay[global] deprecated class ArrayType extends Type { ArrayType() { this instanceof @tuple_type or @@ -2061,6 +2082,7 @@ deprecated class ArrayType extends Type { * * An array type such as `Array`, or equivalently, `string[]`. */ +overlay[global] deprecated class PlainArrayType extends ArrayType, TypeReference { PlainArrayType() { this.hasQualifiedName("Array") } @@ -2075,6 +2097,7 @@ deprecated class PlainArrayType extends ArrayType, TypeReference { * * A read-only array type such as `ReadonlyArray`. */ +overlay[global] deprecated class ReadonlyArrayType extends ArrayType, TypeReference { ReadonlyArrayType() { this.hasQualifiedName("ReadonlyArray") } } @@ -2087,6 +2110,7 @@ deprecated class ReadonlyArrayType extends ArrayType, TypeReference { * * A tuple type, such as `[number, string]`. */ +overlay[global] deprecated class TupleType extends ArrayType, @tuple_type { /** * Gets the `i`th member of this tuple type, starting at 0. @@ -2148,6 +2172,7 @@ deprecated class TupleType extends ArrayType, @tuple_type { * * The predefined `any` type. */ +overlay[global] deprecated class AnyType extends Type, @any_type { } /** @@ -2158,6 +2183,7 @@ deprecated class AnyType extends Type, @any_type { } * * The predefined `unknown` type. */ +overlay[global] deprecated class UnknownType extends Type, @unknown_type { } /** @@ -2168,6 +2194,7 @@ deprecated class UnknownType extends Type, @unknown_type { } * * The predefined `string` type. */ +overlay[global] deprecated class StringType extends Type, @string_type { } /** @@ -2178,6 +2205,7 @@ deprecated class StringType extends Type, @string_type { } * * The predefined `number` type. */ +overlay[global] deprecated class NumberType extends Type, @number_type { } /** @@ -2188,6 +2216,7 @@ deprecated class NumberType extends Type, @number_type { } * * The predefined `bigint` type. */ +overlay[global] deprecated class BigIntType extends Type, @bigint_type { } /** @@ -2198,6 +2227,7 @@ deprecated class BigIntType extends Type, @bigint_type { } * * A boolean, number, or string literal type. */ +overlay[global] deprecated class LiteralType extends Type, @literal_type { /** * Gets the string value of this literal. @@ -2213,6 +2243,7 @@ deprecated class LiteralType extends Type, @literal_type { * * The boolean literal type `true` or `false`. */ +overlay[global] deprecated class BooleanLiteralType extends LiteralType, @boolean_literal_type { /** * Gets the boolean value represented by this type. @@ -2227,6 +2258,7 @@ deprecated class BooleanLiteralType extends LiteralType, @boolean_literal_type { /** * A number literal as a static type. */ +overlay[global] deprecated class NumberLiteralType extends LiteralType, @number_literal_type { override string getStringValue() { type_literal_value(this, result) } @@ -2249,6 +2281,7 @@ deprecated class NumberLiteralType extends LiteralType, @number_literal_type { * * A string literal as a static type. */ +overlay[global] deprecated class StringLiteralType extends LiteralType, @string_literal_type { override string getStringValue() { type_literal_value(this, result) } } @@ -2261,6 +2294,7 @@ deprecated class StringLiteralType extends LiteralType, @string_literal_type { * * A bigint literal as a static type. */ +overlay[global] deprecated class BigIntLiteralType extends LiteralType { override string getStringValue() { type_literal_value(this, result) } @@ -2283,6 +2317,7 @@ deprecated class BigIntLiteralType extends LiteralType { * * The `boolean` type, internally represented as the union type `true | false`. */ +overlay[global] deprecated class BooleanType extends UnionType { BooleanType() { this.getAnElementType() instanceof @true_type and @@ -2299,6 +2334,7 @@ deprecated class BooleanType extends UnionType { * * The `string` type or a string literal type. */ +overlay[global] deprecated class StringLikeType extends Type { StringLikeType() { this instanceof StringType or @@ -2314,6 +2350,7 @@ deprecated class StringLikeType extends Type { * * The `number` type or a number literal type. */ +overlay[global] deprecated class NumberLikeType extends Type { NumberLikeType() { this instanceof NumberType or @@ -2329,6 +2366,7 @@ deprecated class NumberLikeType extends Type { * * The `boolean`, `true,` or `false` type. */ +overlay[global] deprecated class BooleanLikeType extends Type { BooleanLikeType() { this instanceof BooleanType or @@ -2344,6 +2382,7 @@ deprecated class BooleanLikeType extends Type { * * The `void` type. */ +overlay[global] deprecated class VoidType extends Type, @void_type { } /** @@ -2354,6 +2393,7 @@ deprecated class VoidType extends Type, @void_type { } * * The `undefined` type. */ +overlay[global] deprecated class UndefinedType extends Type, @undefined_type { } /** @@ -2364,6 +2404,7 @@ deprecated class UndefinedType extends Type, @undefined_type { } * * The `null` type. */ +overlay[global] deprecated class NullType extends Type, @null_type { } /** @@ -2374,6 +2415,7 @@ deprecated class NullType extends Type, @null_type { } * * The `never` type. */ +overlay[global] deprecated class NeverType extends Type, @never_type { } /** @@ -2384,6 +2426,7 @@ deprecated class NeverType extends Type, @never_type { } * * The `symbol` type or a specific `unique symbol` type. */ +overlay[global] deprecated class SymbolType extends Type, @symbol_type { } /** @@ -2394,6 +2437,7 @@ deprecated class SymbolType extends Type, @symbol_type { } * * The `symbol` type. */ +overlay[global] deprecated class PlainSymbolType extends SymbolType, @plain_symbol_type { } /** @@ -2404,6 +2448,7 @@ deprecated class PlainSymbolType extends SymbolType, @plain_symbol_type { } * * A `unique symbol` type. */ +overlay[global] deprecated class UniqueSymbolType extends SymbolType, @unique_symbol_type { /** * Gets the canonical name of the variable exposing the symbol. @@ -2438,6 +2483,7 @@ deprecated class UniqueSymbolType extends SymbolType, @unique_symbol_type { * * The `object` type. */ +overlay[global] deprecated class ObjectKeywordType extends Type, @objectkeyword_type { } /** @@ -2448,6 +2494,7 @@ deprecated class ObjectKeywordType extends Type, @objectkeyword_type { } * * A type that refers to a class, interface, enum, or enum member. */ +overlay[global] deprecated class TypeReference extends Type, @type_reference { /** * Gets the canonical name of the type being referenced. @@ -2506,6 +2553,7 @@ deprecated class TypeReference extends Type, @type_reference { * * A type that refers to a class, possibly with type arguments. */ +overlay[global] deprecated class ClassType extends TypeReference { ClassDefinition declaration; @@ -2525,6 +2573,7 @@ deprecated class ClassType extends TypeReference { * * A type that refers to an interface, possibly with type arguents. */ +overlay[global] deprecated class InterfaceType extends TypeReference { InterfaceDeclaration declaration; @@ -2544,6 +2593,7 @@ deprecated class InterfaceType extends TypeReference { * * A type that refers to an enum. */ +overlay[global] deprecated class EnumType extends TypeReference { EnumDeclaration declaration; @@ -2563,6 +2613,7 @@ deprecated class EnumType extends TypeReference { * * A type that refers to the value of an enum member. */ +overlay[global] deprecated class EnumLiteralType extends TypeReference { EnumMember declaration; @@ -2582,6 +2633,7 @@ deprecated class EnumLiteralType extends TypeReference { * * A type that refers to a type alias. */ +overlay[global] deprecated class TypeAliasReference extends TypeReference { TypeAliasReference() { type_alias(this, _) } @@ -2601,6 +2653,7 @@ deprecated class TypeAliasReference extends TypeReference { * * An anonymous interface type, such as `{ x: number }`. */ +overlay[global] deprecated class AnonymousInterfaceType extends Type, @object_type { } /** @@ -2611,6 +2664,7 @@ deprecated class AnonymousInterfaceType extends Type, @object_type { } * * A type that refers to a type variable. */ +overlay[global] deprecated class TypeVariableType extends Type, @typevariable_type { /** * Gets a syntactic declaration of this type variable. @@ -2656,6 +2710,7 @@ deprecated class TypeVariableType extends Type, @typevariable_type { * * A type that refers to a type variable declared on a class, interface or function. */ +overlay[global] deprecated class CanonicalTypeVariableType extends TypeVariableType, @canonical_type_variable_type { override TypeName getHostType() { result = this.getCanonicalName().getParent() } @@ -2681,6 +2736,7 @@ deprecated class CanonicalTypeVariableType extends TypeVariableType, @canonical_ * - `(x: T) => T` * - `(x: S, y: T) => T`. */ +overlay[global] deprecated class LexicalTypeVariableType extends TypeVariableType, @lexical_type_variable_type { override string getName() { types(this, _, result) // The toString value contains the name. @@ -2703,6 +2759,7 @@ deprecated class LexicalTypeVariableType extends TypeVariableType, @lexical_type * } * ``` */ +overlay[global] deprecated class ThisType extends Type, @this_type { /** * Gets the type containing the `this` type. @@ -2721,6 +2778,7 @@ deprecated class ThisType extends Type, @this_type { * The type of a named value, `typeof X`, typically denoting the type of * a class constructor, namespace object, enum object, or module object. */ +overlay[global] deprecated class TypeofType extends Type, @typeof_type { /** * Gets the canonical name of the named value. @@ -2801,6 +2859,7 @@ module SignatureKind { * * A function or constructor signature in a TypeScript type. */ +overlay[global] deprecated class CallSignatureType extends @signature_type { /** * Gets a value indicating if this is a function or constructor signature. @@ -2955,6 +3014,7 @@ deprecated class CallSignatureType extends @signature_type { * * A function call signature in a type, that is, a signature without the `new` keyword. */ +overlay[global] deprecated class FunctionCallSignatureType extends CallSignatureType, @function_signature_type { } /** @@ -2965,6 +3025,7 @@ deprecated class FunctionCallSignatureType extends CallSignatureType, @function_ * * A constructor call signature in a type, that is, a signature with the `new` keyword. */ +overlay[global] deprecated class ConstructorCallSignatureType extends CallSignatureType, @constructor_signature_type { } @@ -2976,6 +3037,7 @@ deprecated class ConstructorCallSignatureType extends CallSignatureType, @constr * - It has one type parameter, say, `T` * - It has a `then` method whose first argument is a callback that takes a `T` as argument. */ +overlay[global] deprecated private class PromiseTypeName extends TypeName { PromiseTypeName() { // The name must suggest it is a promise. @@ -3005,6 +3067,7 @@ deprecated private class PromiseTypeName extends TypeName { * This includes types whose name and `then` method signature suggest it is a promise, * such as `PromiseLike` and `Thenable`. */ +overlay[global] deprecated class PromiseType extends TypeReference { PromiseType() { this.getNumTypeArgument() = 1 and diff --git a/javascript/ql/lib/semmle/javascript/Unit.qll b/javascript/ql/lib/semmle/javascript/Unit.qll index 83a4a03321d9..e31457eae1aa 100644 --- a/javascript/ql/lib/semmle/javascript/Unit.qll +++ b/javascript/ql/lib/semmle/javascript/Unit.qll @@ -1,3 +1,5 @@ /** Provides the `Unit` class. */ +overlay[local?] +module; import codeql.util.Unit diff --git a/javascript/ql/lib/semmle/javascript/Util.qll b/javascript/ql/lib/semmle/javascript/Util.qll index 701ef2b58311..ef3784e2e384 100644 --- a/javascript/ql/lib/semmle/javascript/Util.qll +++ b/javascript/ql/lib/semmle/javascript/Util.qll @@ -1,6 +1,8 @@ /** * Provides general-purpose utility predicates. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/Variables.qll b/javascript/ql/lib/semmle/javascript/Variables.qll index adc0ad5b9c87..5fa7473c3043 100644 --- a/javascript/ql/lib/semmle/javascript/Variables.qll +++ b/javascript/ql/lib/semmle/javascript/Variables.qll @@ -1,4 +1,6 @@ /** Provides classes for modeling program variables. */ +overlay[local] +module; import javascript @@ -62,6 +64,7 @@ class LocalScope extends Scope { */ class ModuleScope extends Scope, @module_scope { /** Gets the module that induces this scope. */ + overlay[global] Module getModule() { result = this.getScopeElement() } override string toString() { result = "module scope" } @@ -256,6 +259,7 @@ class VarRef extends @varref, Identifier, BindingPattern, LexicalRef { override VarRef getABindingVarRef() { result = this } + overlay[global] override predicate isImpure() { none() } override Expr getUnderlyingReference() { result = this } @@ -543,6 +547,7 @@ class ArrayPattern extends DestructuringPattern, @array_pattern { /** Holds if this array pattern has an omitted element. */ predicate hasOmittedElement() { this.elementIsOmitted(_) } + overlay[global] override predicate isImpure() { this.getAnElement().isImpure() } override VarRef getABindingVarRef() { @@ -583,6 +588,7 @@ class ObjectPattern extends DestructuringPattern, @object_pattern { /** Gets the rest property pattern of this object pattern, if any. */ override Expr getRest() { result = this.getChildExpr(-1) } + overlay[global] override predicate isImpure() { this.getAPropertyPattern().isImpure() } override VarRef getABindingVarRef() { @@ -640,6 +646,7 @@ class PropertyPattern extends @property, AstNode { ObjectPattern getObjectPattern() { properties(this, result, _, _, _) } /** Holds if this pattern is impure, that is, if its evaluation could have side effects. */ + overlay[global] predicate isImpure() { this.isComputed() and this.getNameExpr().isImpure() or @@ -844,6 +851,7 @@ class SimpleParameter extends Parameter, VarDecl { * Gets a use of this parameter that refers to its initial value as * passed in from the caller. */ + overlay[global] VarUse getAnInitialUse() { exists(SsaDefinition ssa | ssa.getAContributingVarDef() = this and diff --git a/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll b/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll index 43cd337685db..411eb24dc6b9 100644 --- a/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll +++ b/javascript/ql/lib/semmle/javascript/ViewComponentInput.qll @@ -1,6 +1,8 @@ /** * Provides a classes and predicates for contributing to the `view-component-input` threat model. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/XML.qll b/javascript/ql/lib/semmle/javascript/XML.qll index 54157809260b..ca401bd3f4be 100644 --- a/javascript/ql/lib/semmle/javascript/XML.qll +++ b/javascript/ql/lib/semmle/javascript/XML.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with XML files and their content. */ +overlay[local] +module; import semmle.files.FileSystem private import codeql.xml.Xml diff --git a/javascript/ql/lib/semmle/javascript/YAML.qll b/javascript/ql/lib/semmle/javascript/YAML.qll index a312d78b6fbe..01473226b44a 100644 --- a/javascript/ql/lib/semmle/javascript/YAML.qll +++ b/javascript/ql/lib/semmle/javascript/YAML.qll @@ -4,6 +4,8 @@ * YAML documents are represented as abstract syntax trees whose nodes * are either YAML values or alias nodes referring to another YAML value. */ +overlay[local] +module; import javascript private import codeql.yaml.Yaml as LibYaml diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll b/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll index e9d05d56e26a..dbb589efb33c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AbstractProperties.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.internal.AbstractValuesImpl private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll b/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll index 41509516cc16..c5d9993dbb75 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AbstractValues.qll @@ -37,6 +37,8 @@ * they represent; additionally, indefinite abstract values record * the source of imprecision that caused them to arise. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.internal.AbstractValuesImpl @@ -57,6 +59,7 @@ class AbstractValue extends TAbstractValue { * Gets the Boolean value some concrete value represented by this * abstract value coerces to. */ + pragma[nomagic] abstract boolean getBooleanValue(); /** @@ -97,6 +100,7 @@ class AbstractValue extends TAbstractValue { * In all cases, purely local flow tracking is used to find prototype objects, so * this predicate cannot be relied on to compute all possible prototype objects. */ + overlay[global] DefiniteAbstractValue getAPrototype() { exists(AbstractProtoProperty proto | proto.getBase() = this and diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll index d0deff8788ca..83d523e07094 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalFlowSteps.qll @@ -33,21 +33,25 @@ private import semmle.javascript.internal.CachedStages * Note: For performance reasons, all subclasses of this class should be part * of the standard library. Use `isAdditionalFlowStep` for query-specific flow steps. */ +overlay[local] class AdditionalFlowStep extends Unit { /** * Holds if `pred` → `succ` should be considered a value-preserving data flow edge.f */ + overlay[global] predicate step(DataFlow::Node pred, DataFlow::Node succ) { none() } /** * Holds if `pred` → `succ` should be considered a value-preserving data flow edge that * crosses calling contexts. */ + overlay[global] predicate jumpStep(DataFlow::Node pred, DataFlow::Node succ) { none() } /** * Holds if `pred` should be stored in the given `content` of the object `succ`. */ + overlay[global] predicate storeStep(DataFlow::Node pred, DataFlow::ContentSet contents, DataFlow::Node succ) { none() } @@ -55,6 +59,7 @@ class AdditionalFlowStep extends Unit { /** * Holds if the given `content` of the object in `pred` should be read into `succ`. */ + overlay[global] predicate readStep(DataFlow::Node pred, DataFlow::ContentSet contents, DataFlow::Node succ) { none() } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll index a0752d768fa5..41b8cb9cfe2b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/AdditionalTaintSteps.qll @@ -1,6 +1,8 @@ /** * Note: The contents of this file are exposed with the `TaintTracking::` prefix, via an import in `TaintTracking.qll`. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll b/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll index bc527b500c96..df0ce747a56b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/BackwardExploration.qll @@ -1,6 +1,7 @@ /** * Alias for the library `semmle.javascript.explore.BackwardDataFlow`. */ +overlay[local?] deprecated module; import semmle.javascript.explore.BackwardDataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll index f773000c8cc3..3b4a6be84d03 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Configuration.qll @@ -625,15 +625,19 @@ abstract deprecated class LabeledBarrierGuardNode extends BarrierGuardNode { * * For use with load/store steps in `DataFlow::SharedFlowStep` and TypeTracking. */ +overlay[local] module PseudoProperties { /** Holds if `s` is a pseudo-property. */ bindingset[s] + overlay[caller] predicate isPseudoProperty(string s) { s.matches("$%$") } bindingset[s] + overlay[caller] private string pseudoProperty(string s) { result = "$" + s + "$" } bindingset[s, v] + overlay[caller] private string pseudoProperty(string s, string v) { result = "$" + s + "|" + v + "$" } /** @@ -680,6 +684,7 @@ module PseudoProperties { * Gets a pseudo-property for the location of a map value where the key is `key`. * The string value of the `key` is encoded in the result, and there is only a result if the string value of `key` is known. */ + overlay[caller] pragma[inline] string mapValueKnownKey(DataFlow::Node key) { result = mapValueKey(any(string s | key.mayHaveStringValue(s))) @@ -689,17 +694,20 @@ module PseudoProperties { * Gets a pseudo-property for the location of a map value where the key is `key`. */ bindingset[key] + overlay[caller] string mapValueKey(string key) { result = pseudoProperty("mapValue", key) } /** * Holds if `prop` equals `mapValueKey(key)` for some value of `key`. */ bindingset[prop] + overlay[caller] predicate isMapValueKey(string prop) { prop.matches("$mapValue|%$") } /** * Gets a pseudo-property for the location of a map value where the key is `key`. */ + overlay[caller] pragma[inline] string mapValue(DataFlow::Node key) { result = mapValueKnownKey(key) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll b/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll index 5a762f4aa1bb..3c12284d77b5 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/CustomAbstractValueDefinitions.qll @@ -7,6 +7,8 @@ * For performance reasons, all subclasses of `CustomAbstractValueDefinition` * should be part of the standard library. */ +overlay[local] +module; private import javascript private import internal.AbstractValuesImpl @@ -32,6 +34,7 @@ class CustomAbstractValueFromDefinition extends AbstractValue, TCustomAbstractVa override predicate isIndefinite(DataFlow::Incompleteness cause) { def.isIndefinite(cause) } + overlay[global] override DefiniteAbstractValue getAPrototype() { result = def.getAPrototype() } override predicate hasLocationInfo( @@ -98,6 +101,7 @@ abstract class CustomAbstractValueDefinition extends Locatable { * Gets an abstract value that represents a prototype object of the * induced abstract value. */ + overlay[global] AbstractValue getAPrototype() { exists(AbstractProtoProperty proto | proto.getBase() = this.getAbstractValue() and @@ -119,6 +123,7 @@ abstract class CustomAbstractValueDefinition extends Locatable { /** * Flow analysis for custom abstract values. */ +overlay[global] class CustomAbstractValueFromDefinitionNode extends DataFlow::AnalyzedNode, DataFlow::ValueNode { CustomAbstractValueFromDefinition val; diff --git a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll index 071d6d084333..d7fa6ba27623 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/DataFlow.qll @@ -17,6 +17,8 @@ * Flow through global variables, object properties or function calls is not * modeled (except for immediately invoked functions as explained above). */ +overlay[local] +module; import javascript private import internal.CallGraphs @@ -64,9 +66,11 @@ module DataFlow { * `p.getALocalSource()` does _not_ return the corresponding argument, and * `p.isIncomplete("call")` holds. */ + overlay[global] predicate isIncomplete(Incompleteness cause) { isIncomplete(this, cause) } /** Gets type inference results for this data flow node. */ + overlay[global] AnalyzedNode analyze() { result = this } /** Gets the expression corresponding to this data flow node, if any. */ @@ -124,11 +128,13 @@ module DataFlow { int getIntValue() { result = this.asExpr().getIntValue() } /** Gets a function value that may reach this node. */ + overlay[global] final FunctionNode getAFunctionValue() { CallGraph::getAFunctionReference(result, 0).flowsTo(this) } /** Gets a function value that may reach this node with the given `imprecision` level. */ + overlay[global] final FunctionNode getAFunctionValue(int imprecision) { CallGraph::getAFunctionReference(result, imprecision).flowsTo(this) } @@ -137,6 +143,7 @@ module DataFlow { * Gets a function value that may reach this node, * possibly derived from a partial function invocation. */ + overlay[global] final FunctionNode getABoundFunctionValue(int boundArgs) { result = this.getAFunctionValue() and boundArgs = 0 or @@ -192,6 +199,7 @@ module DataFlow { FlowSteps::identityFunctionStep(result, this) } + overlay[global] private NameResolution::Node getNameResolutionNode() { this = valueNode(result) or @@ -205,6 +213,7 @@ module DataFlow { * Holds if this node is annotated with the given named type, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] cached predicate hasUnderlyingType(string globalName) { Stages::TypeTracking::ref() and @@ -218,6 +227,7 @@ module DataFlow { * Holds if this node is annotated with the given named type, * or is declared as a subtype thereof, or is a union or intersection containing such a type. */ + overlay[global] cached predicate hasUnderlyingType(string moduleName, string typeName) { Stages::TypeTracking::ref() and @@ -466,6 +476,7 @@ module DataFlow { /** * Gets an accessor (`get` or `set` method) that may be invoked by this property reference. */ + overlay[global] final DataFlow::FunctionNode getAnAccessorCallee() { result = CallGraph::getAnAccessorCallee(this) } @@ -1419,11 +1430,13 @@ module DataFlow { * This predicate is only defined for expressions, properties, and for statements that declare * a function, a class, or a TypeScript namespace or enum. */ + pragma[nomagic] ValueNode valueNode(AstNode nd) { result.getAstNode() = nd } /** * Gets the data flow node corresponding to `e`. */ + overlay[caller?] pragma[inline] ExprNode exprNode(Expr e) { result = valueNode(e) } @@ -1762,6 +1775,7 @@ module DataFlow { ) } + overlay[global] private class ReflectiveParamsStep extends LegacyPreCallGraphStep { override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) { exists(DataFlow::ReflectiveParametersNode params, DataFlow::FunctionNode f, int i | @@ -1774,6 +1788,7 @@ module DataFlow { } /** A taint step from the reflective parameters node to any parameter. */ + overlay[global] private class ReflectiveParamsTaintStep extends TaintTracking::LegacyTaintStep { override predicate step(DataFlow::Node obj, DataFlow::Node element) { exists(DataFlow::ReflectiveParametersNode params, DataFlow::FunctionNode f | @@ -1787,6 +1802,7 @@ module DataFlow { /** * Holds if there is a step from `pred` to `succ` through a field accessed through `this` in a class. */ + overlay[global] predicate localFieldStep(DataFlow::Node pred, DataFlow::Node succ) { exists(ClassNode cls, string prop | pred = AccessPath::getAnAssignmentTo(cls.getADirectSuperClass*().getAReceiverNode(), prop) or @@ -1819,6 +1835,7 @@ module DataFlow { * `p.getALocalSource()` does _not_ return the corresponding argument, and * `p.isIncomplete("call")` holds. */ + overlay[global] predicate isIncomplete(Node nd, Incompleteness cause) { exists(SsaVariable ssa | nd = TSsaDefNode(ssa.getDefinition()) | defIsIncomplete(ssa.(SsaExplicitDefinition).getDef(), cause) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll b/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll index eb7160683a76..13aa5628111c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/FlowSummary.qll @@ -1,4 +1,6 @@ /** Provides classes and predicates for defining flow summaries. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.internal.sharedlib.FlowSummaryImpl as Impl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll b/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll index 9b9fe218f09d..d96d4756526e 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/ForwardExploration.qll @@ -1,6 +1,7 @@ /** * Alias for the library `semmle.javascript.explore.ForwardDataFlow`. */ +overlay[local?] deprecated module; import semmle.javascript.explore.ForwardDataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll b/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll index b7b2b9ba1e5b..48c21d41d75d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/InferredTypes.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + /** * Types inferred by the flow analysis, represented as type tags. * diff --git a/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll b/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll index 621d18fb472e..bab76c61d6f1 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/LocalObjects.qll @@ -1,6 +1,8 @@ /** * Provides classes for the local objects that the dataflow library can reason about soundly. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll index 0e6394a6f557..d4244ec3cbc6 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll @@ -3,6 +3,8 @@ * as nodes corresponding to function definitions or nodes corresponding to * parameters. */ +overlay[local] +module; private import javascript private import semmle.javascript.dependencies.Dependencies @@ -158,6 +160,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * addEventHandler("click", foo.bind(this, "value of x")) * ``` */ + overlay[global] ParameterNode getABoundCallbackParameter(int callback, int param) { exists(int boundArgs | result = @@ -178,6 +181,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN private ObjectLiteralNode getOptionsArgument(int i) { result.flowsTo(this.getArgument(i)) } /** Gets an abstract value representing possible callees of this call site. */ + overlay[global] final AbstractValue getACalleeValue() { exists(DataFlow::Node callee, DataFlow::AnalyzedNode analyzed | pragma[only_bind_into](callee) = this.getCalleeNode() and @@ -192,6 +196,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * To alter the call graph as seen by the interprocedural data flow libraries, override * the `getACallee(int imprecision)` predicate instead. */ + overlay[global] final Function getACallee() { result = this.getACallee(0) } /** @@ -206,6 +211,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * This predicate can be overridden to alter the call graph used by the interprocedural * data flow libraries. */ + overlay[global] Function getACallee(int imprecision) { result = CallGraph::getACallee(this, imprecision).getFunction() } @@ -214,6 +220,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * Holds if the approximation of possible callees for this call site is * affected by the given analysis incompleteness `cause`. */ + overlay[global] predicate isIndefinite(DataFlow::Incompleteness cause) { this.getACalleeValue().isIndefinite(cause) } @@ -229,6 +236,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * independent contexts, so tracking flow through it leads to * imprecision. */ + overlay[global] predicate isImprecise() { this.isIndefinite("global") and exists(DefiniteAbstractValue v | v = this.getACalleeValue() | not v instanceof AbstractCallable) @@ -238,6 +246,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * Holds if our approximation of possible callees for this call site is * likely to be incomplete. */ + overlay[global] predicate isIncomplete() { // the flow analysis identifies a source of incompleteness other than // global flow (which usually leads to imprecision rather than incompleteness) @@ -248,6 +257,7 @@ class InvokeNode extends DataFlow::SourceNode instanceof DataFlow::Impl::InvokeN * Holds if our approximation of possible callees for this call site is * likely to be imprecise or incomplete. */ + overlay[global] predicate isUncertain() { this.isImprecise() or this.isIncomplete() } /** @@ -763,7 +773,7 @@ module ModuleImportNode { cached ModuleImportNode moduleImport(string path) { // NB. internal modules may be imported with a "node:" prefix - Stages::Imports::ref() and result.getPath() = ["node:" + path, path] + result.getPath() = ["node:" + path, path] } /** @@ -771,6 +781,7 @@ ModuleImportNode moduleImport(string path) { * `require("lodash")` in a context where a package.json file includes * `"lodash"` as a dependency. */ +overlay[global] ModuleImportNode dependencyModuleImport(Dependency dep) { result = dep.getAUse("import").(Import).getImportedModuleNode() } @@ -861,6 +872,7 @@ module MemberKind { * * Additional patterns can be recognized as class nodes, by extending `DataFlow::ClassNode::Range`. */ +overlay[global] class ClassNode extends DataFlow::ValueNode, DataFlow::SourceNode { override AST::ValueNode astNode; AbstractCallable function; @@ -1329,6 +1341,7 @@ class ClassNode extends DataFlow::ValueNode, DataFlow::SourceNode { /** * Helper predicate to get a prototype reference in a file. */ +overlay[global] private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and result.getPropertyName() = "prototype" and @@ -1338,6 +1351,7 @@ private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { /** * Helper predicate to get an instantiation in a file. */ +overlay[global] private DataFlow::NewNode getAnInstantiationInFile(string name, File f) { result = AccessPath::getAReferenceTo(name).(DataFlow::LocalSourceNode).getAnInstantiation() and result.getFile() = f @@ -1346,6 +1360,7 @@ private DataFlow::NewNode getAnInstantiationInFile(string name, File f) { /** * Gets a reference to the function `func`, where there exists a read/write of the "prototype" property on that reference. */ +overlay[global] pragma[noinline] private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) { exists(result.getAPropertyReference("prototype")) and @@ -1353,6 +1368,7 @@ private DataFlow::SourceNode getAFunctionValueWithPrototype(AbstractValue func) func instanceof AbstractCallable // the join-order goes bad if `func` has type `AbstractFunction`. } +overlay[global] module ClassNode { /** * A dataflow node that should be considered a class node. @@ -1435,6 +1451,7 @@ module ClassNode { * _.partial(fn, x, y, z) * ``` */ +overlay[global] class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Range { /** Gets a node holding a callback invoked by this partial invocation node. */ DataFlow::Node getACallbackNode() { @@ -1470,6 +1487,7 @@ class PartialInvokeNode extends DataFlow::Node instanceof PartialInvokeNode::Ran } } +overlay[global] module PartialInvokeNode { /** * A data flow node that performs a partial function application. @@ -1717,6 +1735,7 @@ class RegExpCreationNode extends DataFlow::SourceNode { predicate maybeGlobal() { RegExp::maybeGlobal(this.tryGetFlags()) } /** Gets a data flow node referring to this regular expression. */ + overlay[global] private DataFlow::SourceNode getAReference(DataFlow::TypeTracker t) { t.start() and result = this @@ -1725,6 +1744,7 @@ class RegExpCreationNode extends DataFlow::SourceNode { } /** Gets a data flow node referring to this regular expression. */ + overlay[global] cached DataFlow::SourceNode getAReference() { Stages::FlowSteps::ref() and @@ -1736,6 +1756,7 @@ class RegExpCreationNode extends DataFlow::SourceNode { * A guard node for a variable in a negative condition, such as `x` in `if(!x)`. * Can be added to a `isBarrier` in a data-flow configuration to block flow through such checks. */ +overlay[global] class VarAccessBarrier extends DataFlow::Node { VarAccessBarrier() { exists(ConditionGuardNode guard, SsaRefinementNode refinement | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll b/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll index d8f29c707a60..6f76e45adf91 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Portals.qll @@ -11,6 +11,7 @@ * * The API of this library is not stable yet and may change. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll index 4389a3d031a6..9f38895d5581 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/PromisifyFlow.qll @@ -3,6 +3,8 @@ * This ensures that when you call a promisified user-defined function, * arguments flow to the original function's parameters. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.AdditionalFlowSteps diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll b/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll index feb0187487e5..b1302df6fbc7 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Refinements.qll @@ -27,6 +27,8 @@ * so the refinement can evaluate to both `true` and `false` for the same * candidate value. */ +overlay[local] +module; import javascript private import AbstractValues @@ -45,6 +47,7 @@ abstract class RefinementCandidate extends Expr { /** * Gets a refinement value inferred for this expression in context `ctxt`. */ + overlay[global] pragma[nomagic] abstract RefinementValue eval(RefinementContext ctxt); } @@ -64,6 +67,7 @@ class Refinement extends Expr instanceof RefinementCandidate { /** * Gets a refinement value inferred for this expression in context `ctxt`. */ + overlay[global] RefinementValue eval(RefinementContext ctxt) { result = super.eval(ctxt) } } @@ -71,6 +75,7 @@ class Refinement extends Expr instanceof RefinementCandidate { abstract private class LiteralRefinement extends RefinementCandidate, Literal { override SsaSourceVariable getARefinedVar() { none() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = this.eval() } @@ -78,16 +83,19 @@ abstract private class LiteralRefinement extends RefinementCandidate, Literal { /** * Gets the refinement value that represents this literal. */ + overlay[global] RefinementValue eval() { result = TAny() } } /** A `null` literal, viewed as a refinement expression. */ private class NullLiteralRefinement extends LiteralRefinement, NullLiteral { + overlay[global] override RefinementValue eval() { result = TValueWithType(TTNull()) } } /** A Boolean literal, viewed as a refinement expression. */ private class BoolRefinement extends LiteralRefinement, BooleanLiteral { + overlay[global] override RefinementValue eval() { exists(boolean b | b.toString() = this.getValue() | result = TBoolConstant(b)) } @@ -95,11 +103,13 @@ private class BoolRefinement extends LiteralRefinement, BooleanLiteral { /** A constant string, viewed as a refinement expression. */ private class StringRefinement extends LiteralRefinement, ConstantString { + overlay[global] override RefinementValue eval() { result = TStringConstant(this.getStringValue()) } } /** A numeric literal, viewed as a refinement expression. */ abstract private class NumberRefinement extends LiteralRefinement, NumberLiteral { + overlay[global] override RefinementValue eval() { result = TValueWithType(TTNumber()) } } @@ -112,6 +122,7 @@ abstract private class NumberRefinement extends LiteralRefinement, NumberLiteral private class IntRefinement extends NumberRefinement, NumberLiteral { IntRefinement() { this.getValue().toInt() = 0 } + overlay[global] override RefinementValue eval() { result = TIntConstant(this.getValue().toInt()) } } @@ -123,6 +134,7 @@ private class UndefinedInRefinement extends RefinementCandidate, { override SsaSourceVariable getARefinedVar() { none() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = TValueWithType(TTUndefined()) @@ -135,6 +147,7 @@ private class VariableRefinement extends RefinementCandidate, VarUse { override SsaSourceVariable getARefinedVar() { result = this.getVariable() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { ctxt.appliesTo(this) and result = ctxt.(VarRefinementContext).getAValue() @@ -149,6 +162,7 @@ private class ParRefinement extends RefinementCandidate, ParExpr { result = this.getExpression().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { result = this.getExpression().(RefinementCandidate).eval(ctxt) } @@ -162,6 +176,7 @@ private class TypeofRefinement extends RefinementCandidate, TypeofExpr { result = this.getOperand().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { exists(RefinementValue opVal | opVal = this.getOperand().(RefinementCandidate).eval(ctxt) and @@ -182,6 +197,7 @@ private class EqRefinement extends RefinementCandidate, EqualityTest { result = this.getRightOperand().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { exists(RefinementCandidate l, RefinementValue lv, RefinementCandidate r, RefinementValue rv | l = this.getLeftOperand() and @@ -220,6 +236,7 @@ private class IndexRefinement extends RefinementCandidate, IndexExpr { result = this.getIndex().(RefinementCandidate).getARefinedVar() } + overlay[global] override RefinementValue eval(RefinementContext ctxt) { exists( RefinementCandidate base, RefinementValue baseVal, RefinementCandidate index, @@ -242,6 +259,7 @@ private class IndexRefinement extends RefinementCandidate, IndexExpr { * if any. */ bindingset[s, i] +overlay[global] private RefinementValue evalIndex(StringConstant s, IntConstant i) { result = TStringConstant(s.getValue().charAt(i.getValue())) } @@ -249,6 +267,7 @@ private RefinementValue evalIndex(StringConstant s, IntConstant i) { /** * A context in which a refinement expression is analyzed. */ +overlay[global] newtype TRefinementContext = /** * A refinement context associated with refinement `ref`, specifying that variable `var` @@ -266,6 +285,7 @@ newtype TRefinementContext = /** * A context in which a refinement expression is analyzed. */ +overlay[global] class RefinementContext extends TRefinementContext { /** * Holds if refinement expression `cand` might be analyzed in this context. @@ -280,6 +300,7 @@ class RefinementContext extends TRefinementContext { * A refinement context specifying that some variable is assumed to have one particular * abstract value. */ +overlay[global] class VarRefinementContext extends RefinementContext, TVarRefinementContext { override predicate appliesTo(RefinementCandidate cand) { exists(AnalyzedRefinement ref, SsaSourceVariable var | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll index 7503e5001e0f..85a8a163cba4 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Sources.qll @@ -5,6 +5,8 @@ * Note that unlike `TypeTracking.qll`, this library only performs * local tracking within a function. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.TypeTracking @@ -192,6 +194,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range { * * See `TypeTracker` for more details about how to use this. */ + overlay[global] pragma[inline] DataFlow::SourceNode track(TypeTracker t2, TypeTracker t) { t = t2.step(this, result) } @@ -200,6 +203,7 @@ class SourceNode extends DataFlow::Node instanceof SourceNode::Range { * * See `TypeBackTracker` for more details about how to use this. */ + overlay[global] pragma[inline] DataFlow::SourceNode backtrack(TypeBackTracker t2, TypeBackTracker t) { t2 = t.step(result, this) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll index 862cf1b84274..077c5c106935 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TaintTracking.qll @@ -9,6 +9,8 @@ * specified, and conversely certain nodes or edges can be designated as taint * _sanitizers_ that block flow. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps @@ -1103,6 +1105,7 @@ module TaintTracking { * * This includes steps between synthesized nodes generated by flow summaries. */ + overlay[caller?] pragma[inline] predicate defaultTaintStep(DataFlow::Node node1, DataFlow::Node node2) { TaintTrackingPrivate::defaultAdditionalTaintStep(node1, node2) @@ -1111,6 +1114,7 @@ module TaintTracking { /** * Holds if `node` is seen as a barrier for taint-tracking. */ + overlay[caller?] pragma[inline] predicate defaultSanitizer(DataFlow::Node node) { TaintTrackingPrivate::defaultTaintSanitizer(node) diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll index 32ad78eb2c6d..caafff44e769 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TypeInference.qll @@ -24,6 +24,8 @@ * the sense that all expressions whole value derives (directly or indirectly) from a property * read are marked as indefinite. */ +overlay[local?] +module; private import javascript import AbstractValues @@ -92,10 +94,15 @@ class AnalyzedNode extends DataFlow::Node { PrimitiveType getAPrimitiveType() { result = this.getAValue().toPrimitive().getType() } /** Gets a Boolean value that this node evaluates to. */ + bindingset[this] + overlay[caller?] + pragma[inline_late] boolean getABooleanValue() { result = this.getAValue().getBooleanValue() } /** Gets the unique Boolean value that this node evaluates to, if any. */ - boolean getTheBooleanValue() { forex(boolean bv | bv = this.getABooleanValue() | result = bv) } + overlay[caller?] + pragma[inline] + boolean getTheBooleanValue() { result = unique( | | this.getABooleanValue()) } /** Gets the unique type inferred for this node, if any. */ InferredType getTheType() { result = unique(InferredType t | t = this.getAType()) } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll index e4c8f162972a..16072670da60 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/TypeTracking.qll @@ -5,6 +5,8 @@ * for tracking certain types interprocedurally without computing which source * a given value came from. */ +overlay[local?] +module; private import javascript private import internal.FlowSteps @@ -136,6 +138,7 @@ class TypeTracker extends TTypeTracker { * Gets the summary that corresponds to having taken a forwards * heap and/or inter-procedural step from `pred` to `succ`. */ + overlay[caller?] pragma[inline] TypeTracker step(DataFlow::SourceNode pred, DataFlow::SourceNode succ) { exists(StepSummary summary | @@ -168,6 +171,7 @@ class TypeTracker extends TTypeTracker { * } * ``` */ + overlay[caller?] pragma[inline] TypeTracker smallstep(DataFlow::Node pred, DataFlow::Node succ) { exists(StepSummary summary | @@ -293,6 +297,7 @@ class TypeBackTracker extends TTypeBackTracker { * Gets the summary that corresponds to having taken a backwards * heap and/or inter-procedural step from `succ` to `pred`. */ + overlay[caller?] pragma[inline] TypeBackTracker step(DataFlow::SourceNode pred, DataFlow::SourceNode succ) { exists(StepSummary summary | @@ -325,6 +330,7 @@ class TypeBackTracker extends TTypeBackTracker { * } * ``` */ + overlay[caller?] pragma[inline] TypeBackTracker smallstep(DataFlow::Node pred, DataFlow::Node succ) { exists(StepSummary summary | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll index 6d86e7ea3f25..f1f729dcf798 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractPropertiesImpl.qll @@ -3,6 +3,8 @@ * * Provides the internal representation of abstract properties and related predicates. */ +overlay[local?] +module; import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll index 6bcef1dc4128..97daed1f30a6 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AbstractValuesImpl.qll @@ -3,6 +3,8 @@ * * Provides a representation for abstract values. */ +overlay[local] +module; private import javascript import semmle.javascript.dataflow.AbstractValues diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll index 3bcc36a65773..b7538c7ffbf0 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AccessPaths.qll @@ -14,6 +14,8 @@ * to the same value have the same access paths, so access paths are neither sound nor * complete as an approximation of expression semantics. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll index d7f92ce8dd30..dfa924699ba5 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AdditionalFlowInternal.qll @@ -5,6 +5,7 @@ private import semmle.javascript.dataflow.internal.DataFlowPrivate /** * Gets a data-flow node synthesized using `AdditionalFlowInternal#needsSynthesizedNode`. */ +overlay[local] DataFlow::Node getSynthesizedNode(AstNode node, string tag) { result = TGenericSynthesizedNode(node, tag, _) } @@ -12,6 +13,7 @@ DataFlow::Node getSynthesizedNode(AstNode node, string tag) { /** * An extension to `AdditionalFlowStep` with additional internal-only predicates. */ +overlay[local] class AdditionalFlowInternal extends DataFlow::AdditionalFlowStep { /** * Holds if a data-flow node should be synthesized for the pair `(node, tag)`. @@ -25,10 +27,12 @@ class AdditionalFlowInternal extends DataFlow::AdditionalFlowStep { /** * Holds if `node` should only permit flow of values stored in `contents`. */ + overlay[global] predicate expectsContent(DataFlow::Node node, DataFlow::ContentSet contents) { none() } /** * Holds if `node` should not permit flow of values stored in `contents`. */ + overlay[global] predicate clearsContent(DataFlow::Node node, DataFlow::ContentSet contents) { none() } } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll index b632c0a12e2d..7354ec6707c2 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/AnalyzedParameters.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import VariableTypeInference diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll index 6dd0ebf0bb1c..b55527de1176 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll @@ -3,6 +3,8 @@ * * This version considers all barrier guards to be relevant. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.AccessPaths diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll index f6474ff31867..fb10e74aa9b3 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/BasicExprTypeInference.qll @@ -4,6 +4,8 @@ * Provides classes implementing type inference for most expressions, except for variable * and property accesses. */ +overlay[local?] +module; private import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll index cc4c883381ea..bcc90bec37dc 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -1,6 +1,8 @@ /** * Internal predicates for computing the call graph. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.StepSummary diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll index a5af2737c186..d29a450274e9 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/Contents.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript private import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels private import semmle.javascript.dataflow.internal.FlowSummaryPrivate as FlowSummaryPrivate @@ -194,6 +197,7 @@ module Public { */ class ContentSet extends TContentSet { /** Gets a content that may be stored into when storing into this set. */ + overlay[caller?] pragma[inline] Content getAStoreContent() { result = this.asSingleton() @@ -333,12 +337,14 @@ module Public { /** * A content set containing only the given content. */ + overlay[caller] pragma[inline] ContentSet singleton(Content content) { result.asSingleton() = content } /** * A content set corresponding to the given property name. */ + overlay[caller] pragma[inline] ContentSet property(PropertyName name) { result.asSingleton().asPropertyName() = name } @@ -399,6 +405,7 @@ module Public { * If `bound` is too large, it is truncated to the greatest lower bound we can represent. */ bindingset[bound] + overlay[caller] ContentSet arrayElementLowerBoundFromInt(int bound) { result = arrayElementLowerBound(bound.minimum(getMaxPreciseArrayIndex() + 1)) } @@ -409,6 +416,7 @@ module Public { * If `n` is too large, it is truncated to the greatest lower bound we can represent. */ bindingset[n] + overlay[caller] ContentSet arrayElementFromInt(int n) { result = arrayElementKnown(n) or @@ -448,6 +456,7 @@ module Public { * If `key` is not one of the keys we track precisely, this is mapped to the unknown key instead. */ bindingset[key] + overlay[caller] ContentSet mapValueFromKey(string key) { result = mapValueWithKnownKey(key) or @@ -510,6 +519,7 @@ module Public { * are mapped to their corresponding content sets (which are no longer seen as property names). */ bindingset[propertyName] + overlay[caller] ContentSet fromLegacyProperty(string propertyName) { result = fromLegacyPseudoProperty(propertyName) or diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll index e5ce83d86c85..a5d3407185b8 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowImplConsistency.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import codeql.dataflow.internal.DataFlowImplConsistency private import sharedlib.DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll index 8d54f639cb0a..4a354e1f7593 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowNode.qll @@ -3,6 +3,8 @@ * * Contains the raw data type underlying `DataFlow::Node`. */ +overlay[local] +module; private import javascript private import codeql.util.Boolean diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll index 1a4051ccdf66..24549e7f1e6b 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/DataFlowPrivate.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript private import semmle.javascript.dataflow.internal.CallGraphs private import semmle.javascript.dataflow.internal.DataFlowNode @@ -310,6 +313,7 @@ private predicate returnNodeImpl(DataFlow::Node node, ReturnKind kind) { kind = MkExceptionalReturnKind() } +overlay[global] private DataFlow::Node getAnOutNodeImpl(DataFlowCall call, ReturnKind kind) { kind = MkNormalReturnKind() and result = call.asOrdinaryCall() or @@ -336,10 +340,12 @@ class ReturnNode extends DataFlow::Node { } /** A node that receives an output from a call. */ +overlay[global] class OutNode extends DataFlow::Node { OutNode() { this = getAnOutNodeImpl(_, _) } } +overlay[global] OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { result = getAnOutNodeImpl(call, kind) } cached @@ -416,9 +422,11 @@ abstract class LibraryCallable extends string { LibraryCallable() { any() } /** Gets a call to this library callable. */ + overlay[global] DataFlow::InvokeNode getACall() { none() } /** Same as `getACall()` except this does not depend on the call graph or API graph. */ + overlay[global] DataFlow::InvokeNode getACallSimple() { none() } } @@ -432,6 +440,7 @@ abstract class LibraryCallableInternal extends LibraryCallable { * * Same as `getACall()` but is evaluated later and may depend negatively on `getACall()`. */ + overlay[global] DataFlow::InvokeNode getACallStage2() { none() } } @@ -467,6 +476,7 @@ predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition isParameterNodeImpl(p, c, pos) } +overlay[global] private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition pos) { n = call.asOrdinaryCall().getArgument(pos.asPositional()) or @@ -523,6 +533,7 @@ private predicate isArgumentNodeImpl(Node n, DataFlowCall call, ArgumentPosition ) } +overlay[global] predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) { isArgumentNodeImpl(n, call, pos) } @@ -545,11 +556,13 @@ DataFlowCallable nodeGetEnclosingCallable(Node node) { node instanceof DataFlow::XmlAttributeNode and result.asFileCallable() = node.getFile() } +overlay[global] newtype TDataFlowType = TFunctionType(Function f) or TInstanceType(DataFlow::ClassNode cls) or TAnyType() +overlay[global] class DataFlowType extends TDataFlowType { string toDebugString() { result = @@ -575,6 +588,7 @@ class DataFlowType extends TDataFlowType { /** * Holds if `t1` is strictly stronger than `t2`. */ +overlay[global] predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { // 't1' is a subclass of 't2' t1.asInstanceOfClass() = t2.asInstanceOfClass().getADirectSubClass+() @@ -584,6 +598,7 @@ predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { t2 = TAnyType() } +overlay[global] private DataFlowType getPreciseType(Node node) { exists(Function f | (node = TValueNode(f) or node = TFunctionSelfReferenceNode(f)) and @@ -598,6 +613,7 @@ private DataFlowType getPreciseType(Node node) { result = getPreciseType(node.(PostUpdateNode).getPreUpdateNode()) } +overlay[global] DataFlowType getNodeType(Node node) { result = getPreciseType(node) or @@ -681,19 +697,23 @@ predicate neverSkipInPathGraph(Node node) { node.asExpr() instanceof VarRef } +overlay[global] string ppReprType(DataFlowType t) { none() } +overlay[global] pragma[inline] private predicate compatibleTypesWithAny(DataFlowType t1, DataFlowType t2) { t1 != TAnyType() and t2 = TAnyType() } +overlay[global] pragma[nomagic] private predicate compatibleTypes1(DataFlowType t1, DataFlowType t2) { t1.asInstanceOfClass().getADirectSubClass+() = t2.asInstanceOfClass() } +overlay[global] pragma[inline] predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { t1 = t2 @@ -742,6 +762,7 @@ class ContentApprox extends TContentApprox { } } +overlay[global] pragma[inline] ContentApprox getContentApprox(Content c) { c instanceof MkPropertyContent and result = TApproxPropertyContent() @@ -767,6 +788,7 @@ ContentApprox getContentApprox(Content c) { c instanceof MkCapturedContent and result = TApproxCapturedContent() } +overlay[global] cached private newtype TDataFlowCall = MkOrdinaryCall(DataFlow::InvokeNode node) or @@ -791,6 +813,7 @@ private newtype TDataFlowCall = FlowSummaryImpl::Private::summaryCallbackRange(c, receiver) } +overlay[global] class DataFlowCall extends TDataFlowCall { DataFlowCallable getEnclosingCallable() { none() } // Overridden in subclass @@ -816,6 +839,7 @@ class DataFlowCall extends TDataFlowCall { Location getLocation() { none() } // Overridden in subclass } +overlay[global] private class OrdinaryCall extends DataFlowCall, MkOrdinaryCall { private DataFlow::InvokeNode node; @@ -832,6 +856,7 @@ private class OrdinaryCall extends DataFlowCall, MkOrdinaryCall { override Location getLocation() { result = node.getLocation() } } +overlay[global] private class PartialCall extends DataFlowCall, MkPartialCall { private DataFlow::PartialInvokeNode node; private DataFlow::Node callback; @@ -851,6 +876,7 @@ private class PartialCall extends DataFlowCall, MkPartialCall { override Location getLocation() { result = node.getLocation() } } +overlay[global] private class BoundCall extends DataFlowCall, MkBoundCall { private DataFlow::InvokeNode node; private int boundArgs; @@ -868,6 +894,7 @@ private class BoundCall extends DataFlowCall, MkBoundCall { override Location getLocation() { result = node.getLocation() } } +overlay[global] private class AccessorCall extends DataFlowCall, MkAccessorCall { private DataFlow::PropRef ref; @@ -882,6 +909,7 @@ private class AccessorCall extends DataFlowCall, MkAccessorCall { override Location getLocation() { result = ref.getLocation() } } +overlay[global] class SummaryCall extends DataFlowCall, MkSummaryCall { private FlowSummaryImpl::Public::SummarizedCallable enclosingCallable; private FlowSummaryImpl::Private::SummaryNode receiver; @@ -908,6 +936,7 @@ class SummaryCall extends DataFlowCall, MkSummaryCall { * This is to help ensure captured variables can flow into the lambda in cases where * we can't find its call sites. */ +overlay[global] private class ImpliedLambdaCall extends DataFlowCall, MkImpliedLambdaCall { private Function function; @@ -981,6 +1010,7 @@ class DataFlowExpr = Expr; Node exprNode(DataFlowExpr expr) { result = DataFlow::exprNode(expr) } +overlay[global] pragma[nomagic] predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos @@ -993,6 +1023,7 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { // are only using these in cases where either the call or callee is generated by a flow summary. } +overlay[global] pragma[inline] DataFlowCallable viableCallable(DataFlowCall node) { // Note: we never include call edges externs here, as it negatively affects the field-flow branch limit, @@ -1021,6 +1052,7 @@ DataFlowCallable viableCallable(DataFlowCall node) { result.asSourceCallableNotExterns() = node.asImpliedLambdaCall() } +overlay[global] private DataFlowCall getACallOnThis(DataFlow::ClassNode cls) { result.asOrdinaryCall() = cls.getAReceiverNode().getAPropertyRead().getACall() or @@ -1029,6 +1061,7 @@ private DataFlowCall getACallOnThis(DataFlow::ClassNode cls) { result.asPartialCall().getACallbackNode() = cls.getAReceiverNode().getAPropertyRead() } +overlay[global] private predicate downwardCall(DataFlowCall call) { exists(DataFlow::ClassNode cls | call = getACallOnThis(cls) and @@ -1041,9 +1074,11 @@ private predicate downwardCall(DataFlowCall call) { * Holds if the set of viable implementations that can be called by `call` * might be improved by knowing the call context. */ +overlay[global] predicate mayBenefitFromCallContext(DataFlowCall call) { downwardCall(call) } /** Gets the type of the receiver of `call`. */ +overlay[global] private DataFlowType getThisArgumentType(DataFlowCall call) { exists(DataFlow::Node node | isArgumentNodeImpl(node, call, MkThisParameter()) and @@ -1052,6 +1087,7 @@ private DataFlowType getThisArgumentType(DataFlowCall call) { } /** Gets the type of the 'this' parameter of `call`. */ +overlay[global] private DataFlowType getThisParameterType(DataFlowCallable callable) { exists(DataFlow::Node node | isParameterNodeImpl(node, callable, MkThisParameter()) and @@ -1063,6 +1099,7 @@ private DataFlowType getThisParameterType(DataFlowCallable callable) { * Gets a viable dispatch target of `call` in the context `ctx`. This is * restricted to those `call`s for which a context might make a difference. */ +overlay[global] DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { mayBenefitFromCallContext(call) and result = viableCallable(call) and @@ -1071,16 +1108,19 @@ DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { } bindingset[node, fun] +overlay[caller] pragma[inline_late] private predicate sameContainerAsEnclosingContainer(Node node, Function fun) { node.getContainer() = fun.getEnclosingContainer() } +overlay[global] abstract private class BarrierGuardAdapter extends DataFlow::Node { // Note: avoid depending on DataFlow::FlowLabel here as it will cause these barriers to be re-evaluated predicate blocksExpr(boolean outcome, Expr e) { none() } } +overlay[global] deprecated private class BarrierGuardAdapterSubclass extends BarrierGuardAdapter instanceof DataFlow::AdditionalBarrierGuardNode { override predicate blocksExpr(boolean outcome, Expr e) { super.blocks(outcome, e) } @@ -1092,6 +1132,7 @@ deprecated private class BarrierGuardAdapterSubclass extends BarrierGuardAdapter * * The standard library contains no subclasses of that class; this is for backwards compatibility only. */ +overlay[global] pragma[nomagic] private predicate legacyBarrier(DataFlow::Node node) { node = MakeBarrierGuard::getABarrierNode() @@ -1100,6 +1141,7 @@ private predicate legacyBarrier(DataFlow::Node node) { /** * Holds if `node` should be removed from the local data flow graph, for compatibility with legacy code. */ +overlay[global] pragma[nomagic] private predicate isBlockedLegacyNode(Node node) { // Ignore captured variable nodes for those variables that are handled by the captured-variable library. @@ -1155,6 +1197,7 @@ private predicate imprecisePostUpdateStep(DataFlow::PostUpdateNode postUpdate, D * Holds if there is a value-preserving steps `node1` -> `node2` that might * be cross function boundaries. */ +overlay[global] private predicate valuePreservingStep(Node node1, Node node2) { node1.getASuccessor() = node2 and not isBlockedLegacyNode(node1) and @@ -1223,10 +1266,12 @@ private predicate useUseFlow(Node node1, Node node2) { ) } +overlay[global] predicate simpleLocalFlowStep(Node node1, Node node2, string model) { simpleLocalFlowStep(node1, node2) and model = "" } +overlay[global] predicate simpleLocalFlowStep(Node node1, Node node2) { valuePreservingStep(node1, node2) and nodeGetEnclosingCallable(pragma[only_bind_out](node1)) = @@ -1314,6 +1359,7 @@ private predicate excludedJumpStep(Node node1, Node node2) { * that does not follow a call edge. For example, a step through a global * variable. */ +overlay[global] predicate jumpStep(Node node1, Node node2) { valuePreservingStep(node1, node2) and node1.getContainer() != node2.getContainer() and @@ -1330,6 +1376,7 @@ predicate jumpStep(Node node1, Node node2) { * `node1` references an object with a content `c.getAReadContent()` whose * value ends up in `node2`. */ +overlay[global] predicate readStep(Node node1, ContentSet c, Node node2) { exists(DataFlow::PropRead read | node1 = read.getBase() and @@ -1447,6 +1494,7 @@ private predicate stringifiedNode(Node node) { } /** Gets the post-update node for which `node` is the corresponding pre-update node. */ +pragma[nomagic] private Node getPostUpdateForStore(Node base) { exists(Expr expr | base = TValueNode(expr) and @@ -1469,6 +1517,7 @@ private Node getPostUpdateForStore(Node base) { } /** Gets node to target with a store to the given `base` object.. */ +overlay[caller] pragma[inline] private Node getStoreTarget(DataFlow::Node base) { result = getPostUpdateForStore(base) @@ -1487,6 +1536,7 @@ private int firstSpreadArgumentIndex(InvokeExpr expr) { * `node2` references an object with a content `c.getAStoreContent()` that * contains the value of `node1`. */ +overlay[global] predicate storeStep(Node node1, ContentSet c, Node node2) { exists(DataFlow::PropWrite write | node1 = write.getRhs() and @@ -1545,6 +1595,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) { * any value stored inside `f` is cleared at the pre-update node associated with `x` * in `x.f = newValue`. */ +overlay[global] predicate clearsContent(Node n, ContentSet c) { FlowSummaryPrivate::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c) or @@ -1578,6 +1629,7 @@ predicate clearsContent(Node n, ContentSet c) { * Holds if the value that is being tracked is expected to be stored inside content `c` * at node `n`. */ +overlay[global] predicate expectsContent(Node n, ContentSet c) { FlowSummaryPrivate::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c) or @@ -1602,6 +1654,7 @@ abstract class NodeRegion extends Unit { /** * Holds if the node `n` is unreachable when the call context is `call`. */ +overlay[global] predicate isUnreachableInCall(NodeRegion n, DataFlowCall call) { none() // TODO: could be useful, but not currently implemented for JS } @@ -1635,6 +1688,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) } /** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */ +overlay[global] predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { call.isSummaryCall(_, receiver.(FlowSummaryNode).getSummaryNode()) and exists(kind) or @@ -1646,6 +1700,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } +overlay[global] class ArgumentNode extends DataFlow::Node { ArgumentNode() { isArgumentNodeImpl(this, _, _) } diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll index 1711faa4adeb..0f5eff532586 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSteps.qll @@ -48,6 +48,7 @@ private predicate legacyPostUpdateStep(DataFlow::Node pred, DataFlow::Node succ) * Holds if data can flow in one step from `pred` to `succ`, taking * additional steps from the configuration into account. */ +overlay[caller?] pragma[inline] deprecated predicate localFlowStep( DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration configuration, @@ -519,22 +520,23 @@ private module CachedSteps { predicate receiverPropWrite(Function f, string prop, DataFlow::Node rhs) { DataFlow::thisNode(f).hasPropertyWrite(prop, rhs) } - - /** - * Holds if there is a step from `pred` to `succ` through a call to an identity function. - */ - cached - predicate identityFunctionStep(DataFlow::Node pred, DataFlow::CallNode succ) { - exists(DataFlow::GlobalVarRefNode global | - global.getName() = "Object" and - succ.(DataFlow::MethodCallNode).calls(global, ["freeze", "seal"]) and - pred = succ.getArgument(0) - ) - } } import CachedSteps +/** + * Holds if there is a step from `pred` to `succ` through a call to an identity function. + */ +overlay[local] +cached +predicate identityFunctionStep(DataFlow::Node pred, DataFlow::CallNode succ) { + exists(DataFlow::GlobalVarRefNode global | + global.getName() = "Object" and + succ.(DataFlow::MethodCallNode).calls(global, ["freeze", "seal"]) and + pred = succ.getArgument(0) + ) +} + /** * A utility class that is equivalent to `boolean` but does not require type joining. */ diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll index a5131e4fd64e..509aa79eda8c 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FlowSummaryPrivate.qll @@ -1,6 +1,8 @@ /** * Provides JS specific classes and predicates for defining flow summaries. */ +overlay[local] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowPrivate @@ -140,6 +142,7 @@ string encodeArgumentPosition(ArgumentPosition pos) { ReturnKind getStandardReturnValueKind() { result = MkNormalReturnKind() and Stage::ref() } private module FlowSummaryStepInput implements Private::StepsInputSig { + overlay[global] DataFlowCall getACall(SummarizedCallable sc) { exists(LibraryCallable callable | callable = sc | result.asOrdinaryCall() = diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll index dda1ac7ae34f..7058729f053d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/FunctionWrapperSteps.qll @@ -1,4 +1,6 @@ /** Provides predicates for tracking functions through wrapper functions. */ +overlay[local?] +module; private import javascript private import FlowSteps as FlowSteps diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll index 3134d76d8f16..ddde8232d59d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterModuleTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference across imports. */ +overlay[local?] +module; private import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll index 80de3cb64fdd..cc0ae3264b73 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/InterProceduralTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference across function calls. */ +overlay[local?] +module; private import javascript import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll index a1720d122369..41a156835156 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/PreCallGraphStep.qll @@ -2,6 +2,8 @@ * Provides an extension point for contributing flow edges prior * to call graph construction and type tracking. */ +overlay[local?] +module; private import javascript private import semmle.javascript.Unit diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll index 83b23871222b..e5f8e8405d3d 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/PropertyTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference for properties. */ +overlay[local?] +module; private import javascript import semmle.javascript.dataflow.AbstractProperties diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll index fed492074b6a..a7e79c50ca20 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/StepSummary.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript private import semmle.javascript.dataflow.TypeTracking private import semmle.javascript.internal.CachedStages diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll index 548d06ef64f5..8ea0d82ebd01 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/TaintTrackingPrivate.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.internal.DataFlowPrivate private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll index 8edacdc2f0f9..62892d7e5dbd 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableCapture.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript as js private import semmle.javascript.dataflow.internal.DataFlowNode private import semmle.javascript.dataflow.internal.VariableOrThis diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll index a517e0d91fd0..8a3b79a420fe 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableOrThis.qll @@ -1,3 +1,6 @@ +overlay[local] +module; + private import javascript private import DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll index bbbd967fda80..6dbb87138c73 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/VariableTypeInference.qll @@ -3,6 +3,8 @@ * * Provides classes implementing type inference for variables. */ +overlay[local?] +module; private import javascript private import AbstractValuesImpl diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll index d9e711ee07a8..26fe56c39b1f 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlow.qll @@ -1,4 +1,6 @@ /** Provides the instantiation of the shared data flow library. */ +overlay[local?] +module; private import semmle.javascript.Locations private import codeql.dataflow.DataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll index c911461788dc..c4591d355a78 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowArg.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import DataFlowImplSpecific private import codeql.dataflow.DataFlow as SharedDataFlow diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll index 3ddcb693f540..37e90e8236aa 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import codeql.dataflow.internal.DataFlowImpl private import DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll index 62188d47b809..ce861c45f653 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplCommon.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import DataFlowArg private import codeql.dataflow.internal.DataFlowImplCommon diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll index a8b541c1b318..66ccb42b74ae 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/DataFlowImplSpecific.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript // This file provides the input to FlowSummaryImpl.qll, which is shared via identical-files.json. diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll index bf370eb9a271..707c0db5705e 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/FlowSummaryImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import codeql.dataflow.internal.FlowSummaryImpl private import DataFlowArg diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll index 7e610c3c23ce..edea8ed6c387 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/Ssa.qll @@ -3,6 +3,8 @@ * * JavaScript's old SSA library is still responsible for the ordinary SSA flow. */ +overlay[local] +module; private import javascript as js private import codeql.ssa.Ssa @@ -94,6 +96,7 @@ module SsaDataflowInput implements DataFlowIntegrationInputSig { } } + overlay[caller?] pragma[inline] predicate guardDirectlyControlsBlock(Guard guard, js::Cfg::BasicBlock bb, GuardValue branch) { exists(js::ConditionGuardNode g | diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll index c9acd77db1a4..98926f1b0008 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/SummaryTypeTracker.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import semmle.javascript.Locations private import codeql.typetracking.internal.SummaryTypeTracker private import semmle.javascript.dataflow.internal.DataFlowPrivate as DataFlowPrivate diff --git a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll index e2215a8afc32..eb9c6e49a189 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/internal/sharedlib/TaintTracking.qll @@ -1,4 +1,6 @@ /** Provides the instantiation of the shared taint tracking library. */ +overlay[local?] +module; private import semmle.javascript.Locations private import codeql.dataflow.TaintTracking diff --git a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll index 8ca2add4a274..f3f8ea9334ea 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/Dependencies.qll @@ -2,6 +2,8 @@ * Provides classes for modeling dependencies such as NPM packages * and framework libraries. */ +overlay[local?] +module; import javascript private import FrameworkLibraries diff --git a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll index 9ff96a58fdc6..ca4ece83d02b 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/FrameworkLibraries.qll @@ -25,6 +25,8 @@ * (for example `Bootstrap` and `React`), while other frameworks have * more complex rules for recognizing instances (for example `MooTools`). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll b/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll index 1d091e9219c9..531cd95bd759 100644 --- a/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll +++ b/javascript/ql/lib/semmle/javascript/dependencies/SemVer.qll @@ -1,6 +1,8 @@ /** * Provides classes for working SemVer (Semantic Versioning). */ +overlay[local?] +module; import semmle.javascript.dependencies.Dependencies diff --git a/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll b/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll index 8fcb83729c48..ffdc1228fe7e 100644 --- a/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll +++ b/javascript/ql/lib/semmle/javascript/endpoints/EndpointNaming.qll @@ -27,6 +27,8 @@ * In these cases, we try to make up human-readable names for the endpoints. * We make an effort to make these unambiguous in practice, though this is not always guaranteed. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll b/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll index 18b7c27a2db2..9773e6e5cfe0 100644 --- a/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/explore/BackwardDataFlow.qll @@ -12,6 +12,7 @@ * Backward exploration in particular does not scale on non-trivial code bases and hence is of limited * usefulness as it stands. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll b/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll index 4b7853245603..260408c99d14 100644 --- a/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll +++ b/javascript/ql/lib/semmle/javascript/explore/CallGraph.qll @@ -21,6 +21,8 @@ * * NOTE: This library should only be used for debugging and exploration, not in production code. */ +overlay[local?] +module; import javascript private import DataFlow diff --git a/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll b/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll index 9d435d067b2e..c99609daca4c 100644 --- a/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll +++ b/javascript/ql/lib/semmle/javascript/explore/ForwardDataFlow.qll @@ -10,6 +10,7 @@ * * NOTE: This library should only be used for debugging and exploration, not in production code. */ +overlay[local?] deprecated module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll b/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll index 8d392bc04482..89f66baff391 100644 --- a/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll +++ b/javascript/ql/lib/semmle/javascript/filters/ClassifyFiles.qll @@ -3,6 +3,8 @@ * generated code, test code, externs declarations, library code or * template code. */ +overlay[local?] +module; import semmle.javascript.GeneratedCode import semmle.javascript.frameworks.Testing @@ -100,6 +102,7 @@ predicate isTemplateFile(File f) { * - `"library"`: `f` contains library code; * - `"template"`: `f` contains template code. */ +overlay[caller?] pragma[inline] predicate classify(File f, string category) { isGeneratedCodeFile(f) and category = "generated" diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll index 1eac5888b955..90700b397a4c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AWS.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [AWS-SDK](https://aws.amazon.com/sdk-for-node-js/) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll index b0b26560ff29..71b1ab3d9d69 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ActionsLib.qll @@ -1,6 +1,8 @@ /** * Contains models for `@actions/core` related libraries. */ +overlay[local?] +module; private import javascript private import semmle.javascript.security.dataflow.IndirectCommandInjectionCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll index 9fd24c81a4a4..335a7b397c14 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Angular2.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Angular (also known as Angular 2.x) applications. */ +overlay[local?] +module; private import javascript private import semmle.javascript.security.dataflow.DomBasedXssCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll index a90e1dd4995e..727b2d4224fb 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + /** * Provides classes for working with AngularJS (also known as Angular 1.x) * applications. diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll index 41d14c1e3be4..beb601dcfb9e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSCore.qll @@ -15,6 +15,7 @@ private import AngularJS /** * Holds if `nd` is a reference to the `angular` variable. */ +overlay[local] DataFlow::SourceNode angular() { // either as a global result = DataFlow::globalVarRef("angular") diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll index 29d7fe3bdf66..a74a5c0c7847 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/AngularJSExpressions.qll @@ -6,6 +6,8 @@ * NOTE: The API of this library is not stable yet and may change in * the future. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll index 621156b19f89..7e5e8fab6904 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/DependencyInjections.qll @@ -6,6 +6,8 @@ * NOTE: The API of this library is not stable yet and may change in * the future. */ +overlay[local?] +module; import javascript private import AngularJS diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll index ae8d3b7d9c5f..3a58fcd37b48 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AngularJS/ServiceDefinitions.qll @@ -11,6 +11,8 @@ * NOTE: The API of this library is not stable yet and may change in * the future. */ +overlay[local?] +module; import javascript private import AngularJS diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll b/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll index 77525689fa44..34fe4a63b318 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Anser.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with applications using [anser](https://www.npmjs.com/package/anser). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll index db2487ce46a0..c95b7a8dc6a1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/AsyncPackage.qll @@ -172,6 +172,7 @@ module AsyncPackage { DataFlow::FunctionNode getFinalCallback() { result = this.getCallback(finalCallbackIndex) } } + overlay[local?] private class IterationCallFlowSummary extends DataFlow::SummarizedCallable { private int callbackArgIndex; @@ -219,6 +220,7 @@ module AsyncPackage { * * For example: `data -> result` in `async.sortBy(data, orderingFn, (err, result) => {})`. */ + overlay[local?] private class IterationPreserveTaintStepFlowSummary extends DataFlow::SummarizedCallable { IterationPreserveTaintStepFlowSummary() { this = "async.sortBy" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll b/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll index 1527b655eddf..d9a6ecb9b6a4 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Azure.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Azure](https://github.com/Azure/azure-sdk-for-node) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll index 9ca47fb47276..24cc9d6f3b25 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Babel.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Babel, `.babelrc` files and Babel plugins. */ +overlay[local?] +module; import javascript private import semmle.javascript.internal.paths.PathMapping diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll b/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll index 314a6343c9f0..7049ad8665e8 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Bundling.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for detecting files generated by popular module bundlers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll index fdc820861b14..44d5ed840915 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Cheerio.qll @@ -1,6 +1,8 @@ /** * Provides a model of `cheerio`, a server-side DOM manipulation library with a jQuery-like API. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.dataflow.DomBasedXssCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll index 8b2ef364054f..7da85a9540a7 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ClassValidator.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about sanitization via the `class-validator` library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll b/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll index b5ae5d275692..27c92237e666 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Classnames.qll @@ -1,6 +1,8 @@ /** * Provides taint steps modeling flow through the `classnames` and `clsx` libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll index 22db9f24b99e..9da93400ef92 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ClientRequests.qll @@ -198,6 +198,7 @@ module ClientRequest { private string urlPropertyName() { result = "url" or result = "uri" } /** An API entry-point for the global variable `axios`. */ + overlay[local?] private class AxiosGlobalEntryPoint extends API::EntryPoint { AxiosGlobalEntryPoint() { this = "axiosGlobal" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll b/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll index ef69d2a3c3fb..89a38bbbb63a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ClosureLibrary.qll @@ -1,6 +1,8 @@ /** * Provides models for miscellaneous utility functions in the closure standard library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll b/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll index cd8fa34a08eb..5d09cd9cb14b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CommandLineArguments.qll @@ -1,4 +1,6 @@ /** Provides modeling for parsed command line arguments. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll b/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll index 170eca4996c7..f6468e9e2478 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ComposedFunctions.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about composed functions. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll index f6ac5854f4d7..62a34186b023 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Connect.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Connect](https://github.com/senchalabs/connect) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll b/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll index 87956ef38c85..98f38b2e136d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ConnectExpressShared.qll @@ -3,6 +3,8 @@ * [Connect](https://github.com/senchalabs/connect) and * [Express](https://expressjs.com) applications. */ +overlay[local?] +module; import javascript @@ -82,6 +84,7 @@ module ConnectExpressShared { * * `kind` is one of: "error", "request", "response", "next". */ + overlay[caller?] pragma[inline] DataFlow::ParameterNode getRouteParameterHandlerParameter( DataFlow::FunctionNode routeHandler, string kind @@ -96,6 +99,7 @@ module ConnectExpressShared { * * `kind` is one of: "error", "request", "response", "next". */ + overlay[caller?] pragma[inline] DataFlow::ParameterNode getRouteHandlerParameter(DataFlow::FunctionNode routeHandler, string kind) { if routeHandler.getNumParameter() = 4 diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll index cdb411927225..d200c450688b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CookieLibraries.qll @@ -1,6 +1,8 @@ /** * Provides classes for reasoning about cookies. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll index 35119a7d8b8f..48b0a3ee602a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll @@ -2,6 +2,8 @@ * Provides a class for modeling expressions used to supply * credentials. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 9cc76b5f5b8c..f2ba9ce0fc7a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling cryptographic libraries. */ +overlay[local?] +module; import javascript import semmle.javascript.Concepts::Cryptography diff --git a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll index cc7c07c80c19..138e3b05d576 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/D3.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/D3.qll @@ -6,6 +6,7 @@ private import semmle.javascript.security.dataflow.DomBasedXssCustomizations /** Provides classes and predicates modeling aspects of the `d3` library. */ module D3 { /** The global variable `d3` as an entry point for API graphs. */ + overlay[local?] private class D3GlobalEntry extends API::EntryPoint { D3GlobalEntry() { this = "D3GlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll b/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll index c75f7148f507..98b24787e5df 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/DateFunctions.qll @@ -1,4 +1,6 @@ /** Provides taint steps modeling flow through date-manipulation libraries. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll b/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll index 60d96a937c9c..06a9935b6c21 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/DigitalOcean.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [DigitalOcean](https://www.npmjs.com/package/digitalocean) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll b/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll index 7fb13d56f08e..effcccbb9454 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about events from the DOM that introduce tainted data. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll index 796770b96ee0..2d21baac1f98 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Electron.qll @@ -41,6 +41,7 @@ module Electron { BrowserView() { this = DataFlow::moduleMember("electron", "BrowserView").getAnInstantiation() } } + overlay[local?] private class ElectronEntryPoint extends API::EntryPoint { ElectronEntryPoint() { this = "Electron.Browser" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll b/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll index 6d5752f769bc..df5f28bdc8cb 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Emscripten.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Emscripten-generated code. */ +overlay[local?] +module; import javascript import semmle.javascript.GeneratedCode diff --git a/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll b/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll index f466d96dd9de..f4af2e9b34f3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/EventEmitter.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript module EventEmitter { @@ -94,6 +97,7 @@ module EventRegistration { /** * A registration of an event handler on an EventEmitter. */ + overlay[global] abstract class Range extends DataFlow::Node { EventEmitter::Range emitter; @@ -148,6 +152,7 @@ module EventDispatch { /** * A dispatch of an event on an EventEmitter. */ + overlay[global] abstract class Range extends DataFlow::Node { EventEmitter::Range emitter; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll b/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll index 2ef2fcde3868..5704429c42e2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Execa.qll @@ -1,6 +1,8 @@ /** * Models the `execa` library in terms of `FileSystemAccess` and `SystemCommandExecution`. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Express.qll b/javascript/ql/lib/semmle/javascript/frameworks/Express.qll index be3cb7b1ccb8..8b274cf2d483 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Express.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Express.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Express](https://expressjs.com) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.ExpressModules diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll b/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll index 77c7a455b41b..e611c7704541 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ExpressModules.qll @@ -1,6 +1,8 @@ /** * Models of npm modules that are used with Express servers. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll index 26dde3fc78bd..e1e190f98473 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Fastify.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Fastify](https://www.fastify.dev/) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll index 30f07396dccd..51f49146046c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Files.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Files.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with file system libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll b/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll index 51e465ef908b..e0dc12d5c747 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Firebase.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about code using the Firebase API. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll index 26e0d4fe94f6..9f09417c74fc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/FormParsers.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling the server-side form/file parsing libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll b/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll index 7fa72c9a9f04..6da39b270a8a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/GWT.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with GWT-generated code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll index 98b7c2b89f73..c2cdb28e3061 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/GraphQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with GraphQL connectors. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll b/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll index 2d068d6b4bf6..6bced8aafc90 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HTTP.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling common HTTP concepts. */ +overlay[local?] +module; import javascript private import semmle.javascript.DynamicPropertyAccess diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll b/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll index 56fb1fe20ef1..426179687961 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Handlebars.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Handlebars code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll index a6dbf40d1e06..4e08bc731d13 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Hapi.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Hapi](https://hapijs.com/) servers. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/History.qll b/javascript/ql/lib/semmle/javascript/frameworks/History.qll index 37c0057f6c1f..224eb2b4b595 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/History.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/History.qll @@ -5,6 +5,7 @@ import javascript /** Provides classes modeling the [`history`](https://npmjs.org/package/history) library. */ module History { /** The global variable `HistoryLibrary` as an entry point for API graphs. */ + overlay[local?] private class HistoryGlobalEntry extends API::EntryPoint { HistoryGlobalEntry() { this = "HistoryLibrary" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll index 8e91230d3b21..23aacd31db06 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpFrameworks.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import semmle.javascript.frameworks.Express import semmle.javascript.frameworks.Hapi import semmle.javascript.frameworks.Koa diff --git a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll index d5d890b8b83e..9f7f6436a876 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/HttpProxy.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with the [http-proxy](https://www.npmjs.com/package/http-proxy) library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll index 1adaed5b4398..9a94fc26341c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Immutable.qll @@ -13,6 +13,7 @@ private module Immutable { /** * An API entrypoint for the global `Immutable` variable. */ + overlay[local?] private class ImmutableGlobalEntry extends API::EntryPoint { ImmutableGlobalEntry() { this = "ImmutableGlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll b/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll index a9f47a2b6b9f..55a496c02411 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/JWT.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JWT libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll index 923df27bd501..84caa889b82d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Knex.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with [knex](https://knexjs.org). */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll b/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll index c9b4403671d1..01a07c171e83 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Koa.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Koa](https://koajs.com) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll index 2c460fcc3451..e8b389e91ad5 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LazyCache.qll @@ -1,6 +1,8 @@ /** * Models imports through the NPM `lazy-cache` package. */ +overlay[local] +module; import javascript @@ -43,7 +45,7 @@ module LazyCache { pragma[noopt] override DataFlow::Node getImportedModuleNode() { this instanceof LazyCacheImport and - result = this.flow() + result = DataFlow::valueNode(this) or exists(LazyCacheVariable variable, Expr base, PropAccess access, string localName | // To avoid recursion, this should not depend on `SourceNode`. @@ -52,12 +54,13 @@ module LazyCache { access.getBase() = base and localName = this.getLocalAlias() and access.getPropertyName() = localName and - result = access.flow() + result = DataFlow::valueNode(access) ) } } /** A constant path element appearing in a call to a lazy-cache object. */ + overlay[global] deprecated private class LazyCachePathExpr extends PathExpr, ConstantString { LazyCachePathExpr() { this = any(LazyCacheImport rp).getArgument(0) } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll index 1118f05b5065..f43b427955a6 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LdapJS.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [LDAPjs](https://www.npmjs.com/package/ldapjs) */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll index 5a8075ed366a..729e43ddb7d9 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LiveServer.qll @@ -1,6 +1,8 @@ /** * Provides classes modeling the [live-server](https://npmjs.com/package/live-server) package. */ +overlay[local?] +module; import javascript private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared as ConnectExpressShared diff --git a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll index 202586227375..fe07e4f19678 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/LodashUnderscore.qll @@ -9,6 +9,7 @@ module LodashUnderscore { /** * A data flow node that accesses a given member of `lodash` or `underscore`. */ + overlay[local] abstract class Member extends DataFlow::SourceNode { /** Gets the name of the accessed member. */ abstract string getName(); @@ -17,6 +18,7 @@ module LodashUnderscore { /** * An import of `lodash` or `underscore` accessing a given member of that package. */ + overlay[local] private class DefaultMember extends Member { string name; @@ -39,12 +41,14 @@ module LodashUnderscore { * In addition to normal imports, this supports per-method imports such as `require("lodash.map")` and `require("lodash/map")`. * In addition, the global variable `_` is assumed to refer to `lodash` or `underscore`. */ + overlay[local] DataFlow::SourceNode member(string name) { result.(Member).getName() = name } /** * Holds if `name` is the name of a member exported from the `lodash` package * which has a corresponding `lodash.xxx` NPM package. */ + overlay[local] private predicate isLodashMember(string name) { // Can be generated using Object.keys(require('lodash')) name = @@ -181,9 +185,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashEach extends DataFlow::SummarizedCallable { LodashEach() { this = "_.each-like" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["each", "eachRight", "forEach", "forEachRight", "every", "some"]).getACall() } @@ -195,9 +201,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashMap extends DataFlow::SummarizedCallable { LodashMap() { this = "_.map" } + overlay[global] override DataFlow::CallNode getACall() { result = member("map").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -212,9 +220,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashFlatMap extends DataFlow::SummarizedCallable { LodashFlatMap() { this = "_.flatMap" } + overlay[global] override DataFlow::CallNode getACall() { result = member("flatMap").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -232,9 +242,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashFlatMapDeep extends DataFlow::SummarizedCallable { LodashFlatMapDeep() { this = "_.flatMapDeep" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["flatMapDeep", "flatMapDepth"]).getACall() } @@ -254,9 +266,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashReduce extends DataFlow::SummarizedCallable { LodashReduce() { this = "_.reduce-like" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["reduce", "reduceRight"]).getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -271,9 +285,11 @@ module LodashUnderscore { } } + overlay[local] private class LoashSortBy extends DataFlow::SummarizedCallable { LoashSortBy() { this = "_.sortBy-like" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["sortBy", "orderBy"]).getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -287,9 +303,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashMinMaxBy extends DataFlow::SummarizedCallable { LodashMinMaxBy() { this = "_.minBy / _.maxBy" } + overlay[global] override DataFlow::CallNode getACall() { result = member(["minBy", "maxBy"]).getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -299,9 +317,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashPartition extends DataFlow::SummarizedCallable { LodashPartition() { this = "_.partition" } + overlay[global] override DataFlow::CallNode getACall() { result = member("partition").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -311,9 +331,11 @@ module LodashUnderscore { } } + overlay[local] private class UnderscoreMapObject extends DataFlow::SummarizedCallable { UnderscoreMapObject() { this = "_.mapObject" } + overlay[global] override DataFlow::CallNode getACall() { result = member("mapObject").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -330,9 +352,11 @@ module LodashUnderscore { } } + overlay[local] private class LodashTap extends DataFlow::SummarizedCallable { LodashTap() { this = "_.tap" } + overlay[global] override DataFlow::CallNode getACall() { result = member("tap").getACall() } override predicate propagatesFlow(string input, string output, boolean preservesValue) { @@ -342,6 +366,7 @@ module LodashUnderscore { } } + overlay[local?] private class LodashGroupBy extends DataFlow::SummarizedCallable { LodashGroupBy() { this = "_.groupBy" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll index aa0151595dfd..e297dbd7afde 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Logging.qll @@ -32,6 +32,7 @@ private module Console { /** * An API entrypoint for the global `console` variable. */ + overlay[local?] private class ConsoleGlobalEntry extends API::EntryPoint { ConsoleGlobalEntry() { this = "ConsoleGlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll index 344bdc2a40fc..4b8ec89814f1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Markdown.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling common markdown parsers and generators. */ +overlay[local?] +module; import semmle.javascript.Unit import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll b/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll index 0db7b438b7d0..6f37766f2300 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Micro.qll @@ -1,6 +1,8 @@ /** * Provides a model of the `micro` NPM package. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll b/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll index c1b4811e889f..90ba42ae8858 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/MooTools.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with MooTools code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll index d7474aae8ca4..4c32f70b9816 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Nest.qll @@ -140,6 +140,7 @@ module NestJS { } /** API node entry point for custom implementations of `ValidationPipe` (a common pattern). */ + overlay[local?] private class ValidationNodeEntry extends API::EntryPoint { ValidationNodeEntry() { this = "ValidationNodeEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll index 551d325f26af..27e7fb1bcbda 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Next.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Next.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about [Next.js](https://www.npmjs.com/package/next). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll index aeae1afcac30..5b122f636e91 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with NoSQL libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll index c5f8c3d14f1c..5ea54cbb8c0f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/NodeJSLib.qll @@ -8,14 +8,17 @@ import semmle.javascript.security.SensitiveActions private import semmle.javascript.dataflow.internal.PreCallGraphStep module NodeJSLib { + overlay[local] private GlobalVariable processVariable() { variables(result, "process", any(GlobalScope sc)) } + overlay[local] pragma[nomagic] private GlobalVarAccess processExprInTopLevel(TopLevel tl) { result = processVariable().getAnAccess() and tl = result.getTopLevel() } + overlay[local] pragma[nomagic] private GlobalVarAccess processExprInNodeModule() { result = processExprInTopLevel(any(NodeModule m)) @@ -25,6 +28,7 @@ module NodeJSLib { * An access to the global `process` variable in a Node.js module, interpreted as * an import of the `process` module. */ + overlay[local] private class ImplicitProcessImport extends DataFlow::ModuleImportNode::Range { ImplicitProcessImport() { this = DataFlow::exprNode(processExprInNodeModule()) } @@ -256,6 +260,7 @@ module NodeJSLib { DataFlow::Node getRouteHandlerNode() { result = handler } } + overlay[global] abstract private class HeaderDefinition extends Http::Servers::StandardHeaderDefinition { ResponseNode r; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll b/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll index e7431c754dc9..92467a36cfae 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/PkgCloud.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [pkgcloud](https://github.com/pkgcloud/pkgcloud) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll index 1277c1ee133b..1f0f11b2e096 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Prettier.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with the [prettier](https://www.npmjs.com/package/prettier) library. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll b/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll index 11fb0f5ceba5..c0188361e72a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/PropertyProjection.qll @@ -4,6 +4,8 @@ * Subclass `PropertyProjection` to refine the behavior of the analysis on existing property projections. * Subclass `CustomPropertyProjection` to introduce new kinds of property projections. */ +overlay[local] +module; import javascript @@ -137,6 +139,7 @@ private class VarArgsPropertyProjection extends PropertyProjection::Range { /** * A taint step for a property projection. */ +overlay[global] private class PropertyProjectionTaintStep extends TaintTracking::SharedTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { // reading from a tainted object yields a tainted result diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll index 59bb2fc2b137..fe42aac907e2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Puppeteer.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for reasoning about [puppeteer](https://www.npmjs.com/package/puppeteer). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/React.qll b/javascript/ql/lib/semmle/javascript/frameworks/React.qll index d55ace8636df..734685282c8e 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/React.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/React.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with React and Preact code. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll b/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll index a64edda01e99..10578a7b26dc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ReactNative.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [React Native](https://facebook.github.io/react-native) code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll index 78931da585a4..3aaf07f637d9 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Redux.qll @@ -1099,6 +1099,7 @@ module Redux { * Used to catch cases where the `connect` function was not recognized by API graphs (usually because of it being * wrapped in another function, which API graphs won't look through). */ + overlay[local?] private class HeuristicConnectEntryPoint extends API::EntryPoint { HeuristicConnectEntryPoint() { this = "react-redux-connect" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Request.qll b/javascript/ql/lib/semmle/javascript/frameworks/Request.qll index 3551da6f0c13..3ba0f3a2dfcc 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Request.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Request.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [request](https://github.com/request/request) applications. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll index 0adbefc04e8d..e7ee72068683 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Restify.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Restify](https://restify.com/) servers. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll index e95999128659..5c00be8ec62d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/RxJS.qll @@ -1,6 +1,8 @@ /** * Provides taint steps modeling flow through `rxjs` Observable objects. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll index 9d106251a211..58ab4e60c46c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SQL.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with SQL connectors. */ +overlay[local?] +module; import javascript @@ -16,6 +18,7 @@ module SQL { * An dataflow node that sanitizes a string to make it safe to embed into * a SQL command. */ + overlay[global] abstract class SqlSanitizer extends DataFlow::Node { DataFlow::Node input; DataFlow::Node output; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll b/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll index 140797dd5db1..1a5965e0d623 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ServerLess.qll @@ -3,6 +3,8 @@ * E.g. [AWS](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html) or [serverless](https://npmjs.com/package/serverless) * In particular a `RemoteFlowSource` is added for AWS, Alibaba, and serverless. */ +overlay[local?] +module; import javascript private import codeql.serverless.ServerLess diff --git a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll index fc0e366df4b8..0ed4745256f1 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/ShellJS.qll @@ -3,6 +3,8 @@ * * https://www.npmjs.com/package/shelljs */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll index 6f460a842ffc..4ab30594b751 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Snapdragon.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with applications using [snapdragon](https://www.npmjs.com/package/snapdragon). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll index cde7ec561240..4d58b0ecd078 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SocketIO.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [socket.io](https://socket.io). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll b/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll index f79a6f11eae9..78756afb1134 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Spife.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with [Spife](https://github.com/npm/spife) applications. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.HTTP diff --git a/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll b/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll index d729f457ef78..422713eac950 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/StringFormatters.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling string formatting libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll b/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll index 20baafa04755..3b48a3226947 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/SystemCommandExecutors.qll @@ -2,6 +2,8 @@ * Provides concrete classes for data-flow nodes that execute an * operating system command, for instance by spawning a new process. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll index a7286c7a1999..8932c2753ab2 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Templating.qll @@ -1,6 +1,8 @@ /** * Provides predicates for working with templating libraries. */ +overlay[local] +module; import javascript @@ -45,6 +47,7 @@ module Templating { Locatable getParent() { template_placeholder_tag_info(this, result, _) } /** Gets a data flow node representing the value plugged into this placeholder. */ + overlay[global] DataFlow::TemplatePlaceholderTagNode asDataFlowNode() { result.getTag() = this } /** Gets the top-level containing the template expression to be inserted at this placeholder. */ @@ -54,6 +57,7 @@ module Templating { * Holds if this performs raw interpolation, that is, inserts its result * in the output without escaping it. */ + overlay[global] predicate isRawInterpolation() { this.getRawText() .regexpMatch(getLikelyTemplateSyntax(this.getFile()).getRawInterpolationRegexp()) @@ -62,6 +66,7 @@ module Templating { /** * Holds if this performs HTML escaping on the result before inserting it in the template. */ + overlay[global] predicate isEscapingInterpolation() { this.getRawText() .regexpMatch(getLikelyTemplateSyntax(this.getFile()).getEscapingInterpolationRegexp()) @@ -93,6 +98,7 @@ module Templating { * Holds if this placeholder occurs in the definition of another template, which means the output * is susceptible to code injection. */ + overlay[global] predicate isInNestedTemplateContext(string templateType) { templateType = "AngularJS" and AngularJS::isInterpretedByAngularJS(this.getParent()) and @@ -135,6 +141,7 @@ module Templating { * * For example, the call generated from `items | async` would be found by `getAPipeCall("async")`. */ + overlay[global] DataFlow::CallNode getAPipeCall(string name) { result.getCalleeNode().asExpr().(PipeRefExpr).getName() = name } @@ -153,16 +160,19 @@ module Templating { Expr getExpression() { result = this.getChildStmt(0).(ExprStmt).getExpr() } /** Gets the data flow node representing the initialization of the given variable in this scope. */ + overlay[global] DataFlow::Node getVariableInit(string name) { result = DataFlow::ssaDefinitionNode(Ssa::implicitInit(this.getScope().getVariable(name))) } /** Gets a data flow node corresponding to a use of the given template variable within this top-level. */ + overlay[global] DataFlow::SourceNode getAVariableUse(string name) { result = this.getScope().getVariable(name).getAnAccess().flow() } /** Gets a data flow node corresponding to a use of the given template variable within this top-level. */ + overlay[global] DataFlow::SourceNode getAnAccessPathUse(string accessPath) { result = this.getAVariableUse(accessPath) or @@ -177,6 +187,7 @@ module Templating { /** * A place where a template is instantiated or rendered. */ + overlay[global] class TemplateInstantiation extends DataFlow::Node instanceof TemplateInstantiation::Range { /** Gets a data flow node that refers to the instantiated template string, if any. */ DataFlow::SourceNode getOutput() { result = super.getOutput() } @@ -206,6 +217,7 @@ module Templating { } /** Companion module to the `TemplateInstantiation` class. */ + overlay[global] module TemplateInstantiation { abstract class Range extends DataFlow::Node { /** Gets a data flow node that refers to the instantiated template, if any. */ @@ -230,6 +242,7 @@ module Templating { } /** Gets an API node that may flow to `succ` through a template instantiation. */ + overlay[global] private API::Node getTemplateInput(DataFlow::SourceNode succ) { exists(TemplateInstantiation inst, API::Node base, string name | base.asSink() = inst.getTemplateParamsNode() and @@ -258,6 +271,7 @@ module Templating { ) } + overlay[global] private class TemplateInputStep extends DataFlow::SharedFlowStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { getTemplateInput(succ).asSink() = pred @@ -268,6 +282,7 @@ module Templating { * A data flow step from the expression in a placeholder tag to the tag itself, * representing the value plugged into the template. */ + overlay[global] private class TemplatePlaceholderStep extends DataFlow::SharedFlowStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(TemplatePlaceholderTag tag | @@ -281,6 +296,7 @@ module Templating { * A taint step from a `TemplatePlaceholderTag` to the enclosing expression in the * surrounding JavaScript program. */ + overlay[global] private class PlaceholderToGeneratedCodeStep extends TaintTracking::SharedTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(TemplatePlaceholderTag tag | @@ -296,6 +312,7 @@ module Templating { final TemplatePlaceholderTag getAPlaceholder() { result.getFile() = this } /** Gets a template file referenced by this one via a template inclusion tag, such as `{% include foo %}` */ + overlay[global] TemplateFile getAnImportedFile() { result = this.getAPlaceholder().(TemplateInclusionTag).getImportedFile() } @@ -314,6 +331,7 @@ module Templating { * - The root folder is considered unknown, and so a heuristic is used to guess the most * likely template file being referenced. */ + overlay[global] abstract class TemplateFileReference extends DataFlow::Node { /** Gets the value that identifies the template. */ string getValue() { @@ -335,6 +353,7 @@ module Templating { } /** Get file argument of a template instantiation, seen as a template file reference. */ + overlay[global] private class DefaultTemplateFileReference extends TemplateFileReference { DefaultTemplateFileReference() { this = any(TemplateInstantiation inst).getTemplateFileNode() } } @@ -352,6 +371,7 @@ module Templating { * - The root folder is considered unknown, and so a heuristic is used to guess the most * likely template file being referenced. */ + overlay[global] abstract class TemplateFileReferenceString extends string { bindingset[this] TemplateFileReferenceString() { this = this } @@ -382,6 +402,7 @@ module Templating { } /** The value of a template reference node, as a template reference string. */ + overlay[global] private class DefaultTemplateReferenceString extends TemplateFileReferenceString { TemplateFileReference r; @@ -397,6 +418,7 @@ module Templating { } /** The `X` in a path of form `../X`, treated as a separate path string with a different context folder. */ + overlay[global] private class UpwardTraversalSuffix extends TemplateFileReferenceString { TemplateFileReferenceString original; @@ -412,6 +434,7 @@ module Templating { * Gets a "fingerprint" for the given template file, which is used to references * that might refer to it (for pruning purposes only). */ + overlay[global] pragma[nomagic] private string getTemplateFileFingerprint(TemplateFile file) { result = file.getStem() @@ -424,6 +447,7 @@ module Templating { * Gets a "fingerprint" for the given string, which must match one of the fingerprints of * the referenced file (for pruning purposes only). */ + overlay[global] pragma[nomagic] private string getTemplateRefFingerprint(TemplateFileReferenceString ref) { result = ref.getStem() and not result = ["index", ""] @@ -442,6 +466,7 @@ module Templating { * * This is only used to speed up `getAMatchingTarget` by pruning out pairs that can't match. */ + overlay[global] pragma[nomagic] private TemplateFile getAPotentialTarget(TemplateFileReferenceString ref) { getTemplateFileFingerprint(result) = getTemplateRefFingerprint(ref) @@ -467,6 +492,7 @@ module Templating { * Additionally, a file whose stem is `index` matches if `ref` would match the parent folder by * the above rules. For example: `bar` matches `src/bar/index.html`. */ + overlay[global] pragma[nomagic] private TemplateFile getAMatchingTarget(TemplateFileReferenceString ref) { result = getAPotentialTarget(ref) and @@ -491,6 +517,7 @@ module Templating { * The string `list` in `A/components/foo.js` will resolve to `A/views/list.html`, * and vice versa in `B/components/foo.js`. */ + overlay[global] pragma[nomagic] private int getRankOfMatchingTarget( TemplateFile file, Folder baseFolder, TemplateFileReferenceString ref @@ -508,6 +535,7 @@ module Templating { /** * Gets the template file referred to by `ref` when resolved from `baseFolder`. */ + overlay[global] private TemplateFile getBestMatchingTarget(Folder baseFolder, TemplateFileReferenceString ref) { result = max(getAMatchingTarget(ref) as f order by getRankOfMatchingTarget(f, baseFolder, ref)) } @@ -599,6 +627,7 @@ module Templating { override string getAPackageName() { result = "dot" } } + overlay[global] private TemplateSyntax getOwnTemplateSyntaxInFolder(Folder f) { exists(PackageDependencies deps | deps.getADependency(result.getAPackageName(), _) and @@ -606,6 +635,7 @@ module Templating { ) } + overlay[global] private TemplateSyntax getTemplateSyntaxInFolder(Folder f) { result = getOwnTemplateSyntaxInFolder(f) or @@ -613,6 +643,7 @@ module Templating { result = getTemplateSyntaxInFolder(f.getParentContainer()) } + overlay[global] private TemplateSyntax getTemplateSyntaxFromInstantiation(TemplateFile file) { result = any(TemplateInstantiation inst | inst.getTemplateFile() = file).getTemplateSyntax() } @@ -620,6 +651,7 @@ module Templating { /** * Gets a template syntax likely to be used in the given file. */ + overlay[global] TemplateSyntax getLikelyTemplateSyntax(TemplateFile file) { result = getTemplateSyntaxFromInstantiation(file) or @@ -632,6 +664,7 @@ module Templating { } /** A step through the `safe` pipe, which bypasses HTML escaping. */ + overlay[global] private class SafePipeStep extends TaintTracking::SharedTaintStep { override predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(DataFlow::CallNode call | @@ -645,6 +678,7 @@ module Templating { /** * An EJS-style `include` call within a template tag, such as `<%- include(file, { params }) %>`. */ + overlay[global] private class EjsIncludeCallInTemplate extends TemplateInstantiation::Range, DataFlow::CallNode { EjsIncludeCallInTemplate() { exists(TemplatePlaceholderTag tag | @@ -669,6 +703,7 @@ module Templating { * * These API nodes are used in the `getTemplateInput` predicate. */ + overlay[local?] private class IncludeFunctionAsEntryPoint extends API::EntryPoint { IncludeFunctionAsEntryPoint() { this = "IncludeFunctionAsEntryPoint" } @@ -703,6 +738,7 @@ module Templating { string getPath() { result = rawPath.trim().replaceAll("\\", "/").regexpReplaceAll("^\\./", "") } /** Gets the file referenced by this inclusion tag. */ + overlay[global] TemplateFile getImportedFile() { result = this.getPath() @@ -712,6 +748,7 @@ module Templating { } /** The imported string from a template inclusion tag. */ + overlay[global] private class TemplateInclusionPathString extends TemplateFileReferenceString { TemplateInclusionTag tag; @@ -723,6 +760,7 @@ module Templating { /** * A call to a member of the `consolidate` library, seen as a template instantiation. */ + overlay[global] private class ConsolidateCall extends TemplateInstantiation::Range, API::CallNode { string engine; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll b/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll index 248d41062076..c81fe3edb558 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Testing.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JavaScript testing frameworks. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.TestingCustomizations diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll index 29c100234bf9..7837e67f7331 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/TorrentLibraries.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling Torrent libraries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll index ca9de4e481fa..8d32c976c57d 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/TrustedTypes.qll @@ -11,6 +11,7 @@ private import semmle.javascript.security.dataflow.CodeInjectionCustomizations * Module for working with uses of the [Trusted Types API](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API). */ module TrustedTypes { + overlay[local?] private class TrustedTypesEntry extends API::EntryPoint { TrustedTypesEntry() { this = "TrustedTypesEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll b/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll index 7d7a9b107aaa..a2f43aed738a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Typeahead.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with typeahead.js code (https://www.npmjs.com/package/typeahead.js). */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll b/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll index abb51b978bc0..790aec62795b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/UnderscoreDotString.qll @@ -1,6 +1,8 @@ /** * Provides classes for modeling data flow behavior of the Underscore.string library (https://www.npmjs.com/package/underscore.string). */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.AdditionalFlowInternal diff --git a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll index 90dcc886ed43..9097497b4f07 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/UriLibraries.qll @@ -422,9 +422,11 @@ private module ClosureLibraryUri { } } +overlay[local] private class QueryStringStringification extends DataFlow::SummarizedCallable { QueryStringStringification() { this = "query-string stringification" } + overlay[global] override DataFlow::InvokeNode getACall() { result = API::moduleImport(["querystring", "query-string", "querystringify", "qs"]) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll index f571648294c2..1052e91d4c13 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Vue.qll @@ -7,6 +7,7 @@ import semmle.javascript.ViewComponentInput module Vue { /** The global variable `Vue`, as an API graph entry point. */ + overlay[local?] private class GlobalVueEntryPoint extends API::EntryPoint { GlobalVueEntryPoint() { this = "VueEntryPoint" } @@ -18,6 +19,7 @@ module Vue { * * This `EntryPoint` is used by `SingleFileComponent::getOwnOptions()`. */ + overlay[local?] private class VueExportEntryPoint extends API::EntryPoint { VueExportEntryPoint() { this = "VueExportEntryPoint" } @@ -437,6 +439,7 @@ module Vue { * * This entry point is used in `SingleFileComponent::getComponentRef()`. */ + overlay[local?] private class VueFileImportEntryPoint extends API::EntryPoint { VueFileImportEntryPoint() { this = "VueFileImportEntryPoint" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll index 49a9ded864b6..326513914db3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Vuex.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with the `vuex` library. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps @@ -394,6 +396,7 @@ module Vuex { } /** Holds if the two files are considered to be part of the same Vuex app. */ + overlay[caller?] pragma[inline] predicate areFilesInSameVuexApp(File a, File b) { not exists(PackageJson pkg) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll b/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll index dfdee73c9d90..9c24f84ecbc8 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/WebResponse.qll @@ -5,6 +5,7 @@ private import javascript /** Treats `Response` as an entry point for API graphs. */ +overlay[local?] private class ResponseEntryPoint extends API::EntryPoint { ResponseEntryPoint() { this = "global.Response" } @@ -12,6 +13,7 @@ private class ResponseEntryPoint extends API::EntryPoint { } /** Treats `Headers` as an entry point for API graphs. */ +overlay[local?] private class HeadersEntryPoint extends API::EntryPoint { HeadersEntryPoint() { this = "global.Headers" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll b/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll index f71b1cf9e0d6..2ec1b784f19f 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/WebSocket.qll @@ -48,6 +48,7 @@ private predicate areLibrariesCompatible( } /** Treats `WebSocket` as an entry point for API graphs. */ +overlay[local?] private class WebSocketEntryPoint extends API::EntryPoint { WebSocketEntryPoint() { this = "global.WebSocket" } @@ -55,6 +56,7 @@ private class WebSocketEntryPoint extends API::EntryPoint { } /** Treats `SockJS` as an entry point for API graphs. */ +overlay[local?] private class SockJSEntryPoint extends API::EntryPoint { SockJSEntryPoint() { this = "global.SockJS" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll index effd49c632bf..3ce4e78ba3a3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/Webix.qll @@ -9,6 +9,7 @@ private import javascript */ module Webix { /** The global variable `webix` as an entry point for API graphs. */ + overlay[local?] private class WebixGlobalEntry extends API::EntryPoint { WebixGlobalEntry() { this = "WebixGlobalEntry" } diff --git a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll index c0a783c17644..fbe895d8383b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/XmlParsers.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with XML parser APIs. */ +overlay[local?] +module; private import javascript as JS private import JS::DataFlow as DataFlow diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll index 82deb735c629..9e7f94c139b7 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll @@ -48,6 +48,7 @@ private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Rang } } +overlay[local] private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable { string type; string path; @@ -57,6 +58,7 @@ private class SummarizedCallableFromModel extends DataFlow::SummarizedCallable { this = type + ";" + path } + overlay[global] override DataFlow::InvokeNode getACall() { ModelOutput::resolvedSummaryBase(type, path, result) } override predicate propagatesFlow( diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll index c04a85487acf..68f2210bff28 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll @@ -62,6 +62,8 @@ * should be prefixed with a tilde character (`~`). For example, `~Bar` can be used to indicate that * the type is not intended to match a static type. */ +overlay[local?] +module; private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific @@ -490,6 +492,7 @@ private predicate invocationMatchesCallSiteFilter( Specific::invocationMatchesExtraCallSiteFilter(invoke, token) } +overlay[local?] private class TypeModelUseEntry extends API::EntryPoint { private string type; @@ -503,6 +506,7 @@ private class TypeModelUseEntry extends API::EntryPoint { API::Node getNodeForType(string type_) { type = type_ and result = this.getANode() } } +overlay[local?] private class TypeModelDefEntry extends API::EntryPoint { private string type; diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll index c79b1ec80e28..15609cb36363 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExport.qll @@ -1,6 +1,8 @@ /** * Contains an extension of `GraphExport` that relies on API graph specific functionality. */ +overlay[local?] +module; private import ApiGraphModels as Shared private import codeql.mad.dynamic.GraphExport diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll index 4969da43be34..3f38c498f324 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -1,6 +1,8 @@ /** * Defines extensible predicates for contributing library models from data extensions. */ +overlay[local] +module; /** * Holds if the value at `(type, path)` should be seen as a flow diff --git a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll index f0d751ad31b6..7904a2b76c6c 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModelsSpecific.qll @@ -41,6 +41,7 @@ class Location = JS::Location; * The model generator must explicitly generate the step between `(package)` and `(package).foo`, for example. */ bindingset[rawType] +overlay[caller] predicate parseTypeString(string rawType, string package, string qualifiedName) { exists(string regexp | regexp = "('[^']+'|[^.]+)(.*)" and @@ -55,6 +56,7 @@ predicate parseTypeString(string rawType, string package, string qualifiedName) /** * Holds if models describing `package` may be relevant for the analysis of this database. */ +overlay[local] predicate isPackageUsed(string package) { package = "global" or @@ -68,6 +70,7 @@ predicate isPackageUsed(string package) { } bindingset[type] +overlay[local] predicate isTypeUsed(string type) { exists(string package | parseTypeString(type, package, _) and @@ -79,8 +82,10 @@ predicate isTypeUsed(string type) { * Holds if `type` can be obtained from an instance of `otherType` due to * language semantics modeled by `getExtraNodeFromType`. */ +overlay[local] predicate hasImplicitTypeModel(string type, string otherType) { none() } +overlay[local] pragma[nomagic] private predicate parseRelevantTypeString(string rawType, string package, string qualifiedName) { isRelevantFullPath(rawType, _) and @@ -88,6 +93,7 @@ private predicate parseRelevantTypeString(string rawType, string package, string } /** Holds if `global` is a global variable referenced via a the `global` package in a CSV row. */ +overlay[local] private predicate isRelevantGlobal(string global) { exists(AccessPath path, AccessPathToken token | isRelevantFullPath("global", path) and @@ -98,6 +104,7 @@ private predicate isRelevantGlobal(string global) { } /** An API graph entry point for global variables mentioned in a model. */ +overlay[local?] private class GlobalApiEntryPoint extends API::EntryPoint { string global; @@ -190,6 +197,7 @@ API::Node getExtraSuccessorFromNode(API::Node node, AccessPathTokenBase token) { } bindingset[node] +overlay[caller?] pragma[inline_late] private API::Node getAGuardedRouteHandlerApprox(API::Node node) { // For now just get any routing node with the same root (i.e. the same web app), as @@ -230,6 +238,7 @@ private predicate blockFuzzyCall(DataFlow::CallNode call) { isCommonBuiltinMethodName(call.getCalleeName()) } +overlay[caller?] pragma[inline] API::Node getAFuzzySuccessor(API::Node node) { result = node.getAMember() and diff --git a/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll b/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll index 375e87e96466..031c5ceaebc5 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/helmet/Helmet.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with Helmet */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll index 70beadbfa573..f9b07e2bb5f0 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/jQuery.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with jQuery code. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll b/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll index be64f243e46f..9e8d640ba48b 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/xUnit.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with xUnit.js tests. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll index b02863b5a4b7..46f2d58d26b0 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalFrameworks.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll index bd51f29d854e..0b81e0e53fb7 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalPromises.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll index 4809ef738022..a563e4e4d510 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalRouteHandlers.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript private import semmle.javascript.frameworks.ConnectExpressShared diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll index 09695a76f10b..267e97a24ab4 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSinks.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript private import SyntacticHeuristics diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll index a823fa428f90..a7d0a720ca30 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalSources.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript import SyntacticHeuristics diff --git a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll index 48ca553da1b2..681e2450cae4 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/AdditionalTaintSteps.qll @@ -3,6 +3,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll b/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll index ae26e66b3b4f..bcb809f4b066 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/HeuristicSinks.qll @@ -1,6 +1,8 @@ /** * Provides heuristically recognized sinks for security queries. */ +overlay[local?] +module; import javascript private import SyntacticHeuristics diff --git a/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll b/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll index 12356d1bf42b..1a9dd67b7543 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/SyntacticHeuristics.qll @@ -3,6 +3,8 @@ * * INTERNAL: Do not use outside of the `semmle.javascript.heuristics` module. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/heuristics/all.qll b/javascript/ql/lib/semmle/javascript/heuristics/all.qll index 8bb54883b969..c8c36700b4fd 100644 --- a/javascript/ql/lib/semmle/javascript/heuristics/all.qll +++ b/javascript/ql/lib/semmle/javascript/heuristics/all.qll @@ -5,6 +5,8 @@ * * Note: This module should not be a permanent part of the standard library imports. */ +overlay[local?] +module; import AdditionalFrameworks import AdditionalPromises diff --git a/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll b/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll index d8e4a18dfc17..d422c960a8fc 100644 --- a/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll +++ b/javascript/ql/lib/semmle/javascript/internal/BasicBlockInternal.qll @@ -2,6 +2,8 @@ * Provides classes for working with basic blocks, and predicates for computing * liveness information for local variables. */ +overlay[local] +module; import javascript private import semmle.javascript.internal.StmtContainers @@ -318,6 +320,7 @@ module Public { /** * Holds if this basic block strictly dominates `bb`. */ + overlay[caller] pragma[inline] predicate strictlyDominates(ReachableBasicBlock bb) { this = immediateDominator+(bb) } @@ -326,12 +329,14 @@ module Public { * * This predicate is reflexive: each reachable basic block dominates itself. */ + overlay[caller] pragma[inline] predicate dominates(ReachableBasicBlock bb) { this = immediateDominator*(bb) } /** * Holds if this basic block strictly post-dominates `bb`. */ + overlay[caller] pragma[inline] predicate strictlyPostDominates(ReachableBasicBlock bb) { this = immediatePostDominator+(bb) } @@ -340,6 +345,7 @@ module Public { * * This predicate is reflexive: each reachable basic block post-dominates itself. */ + overlay[caller] pragma[inline] predicate postDominates(ReachableBasicBlock bb) { this = immediatePostDominator*(bb) } } diff --git a/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll b/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll index f5f8bfb2d1ef..7c36aa9c0989 100644 --- a/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll +++ b/javascript/ql/lib/semmle/javascript/internal/BindingInfo.qll @@ -1,6 +1,8 @@ /** * Provides a limited public interface to name/type resolution information. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.NameResolution diff --git a/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll b/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll index 98a35692822e..ae9fe0bce271 100644 --- a/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll +++ b/javascript/ql/lib/semmle/javascript/internal/CachedStages.qll @@ -40,6 +40,7 @@ module Stages { /** * The `ast` stage. */ + overlay[local] cached module Ast { /** @@ -84,6 +85,7 @@ module Stages { /** * The `basicblocks` stage. */ + overlay[local] cached module BasicBlocks { /** @@ -110,6 +112,7 @@ module Stages { /** * The part of data flow computed before flow summary nodes. */ + overlay[local] cached module EarlyDataFlowStage { /** @@ -134,6 +137,7 @@ module Stages { /** * The `dataflow` stage. */ + overlay[local] cached module DataFlowStage { /** @@ -167,8 +171,8 @@ module Stages { or exists(any(DataFlow::PropRef ref).getBase()) or - exists(any(DataFlow::ClassNode cls)) - or + // exists(any(DataFlow::ClassNode cls)) // Depends on AnalyzedNode + // or exists(any(DataFlow::CallNode node).getArgument(_)) or exists(any(DataFlow::CallNode node).getAnArgument()) @@ -202,8 +206,6 @@ module Stages { or exists(any(Import i).getImportedModule()) or - exists(DataFlow::moduleImport(_)) - or exists(any(ReExportDeclaration d).getReExportedModule()) or exists(any(Module m).getABulkExportedNode()) diff --git a/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll b/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll index 43ae4ffd43e6..adb09ffc599a 100644 --- a/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll +++ b/javascript/ql/lib/semmle/javascript/internal/NameResolution.qll @@ -1,6 +1,8 @@ /** * Provides name resolution and propagates type information. */ +overlay[local?] +module; private import javascript @@ -401,6 +403,7 @@ module NameResolution { /** * Holds if data should propagate from `node1` to `node2`. */ + overlay[caller?] pragma[inline] predicate step(Node node1, Node node2) { commonStep(node1, node2) diff --git a/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll b/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll index a1df0504ce81..741575c3242c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll +++ b/javascript/ql/lib/semmle/javascript/internal/StmtContainers.qll @@ -4,6 +4,8 @@ * Provides predicates and classes for relating nodes to their * enclosing `StmtContainer`. */ +overlay[local] +module; private import javascript private import semmle.javascript.internal.CachedStages @@ -46,6 +48,7 @@ class NodeInStmtContainer extends Locatable, @node_in_stmt_container { /** * Gets the function or toplevel to which this node belongs. */ + overlay[caller] pragma[inline] final StmtContainer getContainer() { result = getStmtContainer(this) } } diff --git a/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll b/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll index 73885f833051..181f673bc25e 100644 --- a/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll +++ b/javascript/ql/lib/semmle/javascript/internal/TypeResolution.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.internal.NameResolution::NameResolution private import semmle.javascript.internal.UnderlyingTypes diff --git a/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll b/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll index 5461cb3d50f2..a657f6d9f8d5 100644 --- a/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll +++ b/javascript/ql/lib/semmle/javascript/internal/UnderlyingTypes.qll @@ -1,6 +1,8 @@ /** * Provides name resolution and propagates type information. */ +overlay[local?] +module; private import javascript private import semmle.javascript.internal.NameResolution::NameResolution diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll index dfbe9ef7da31..79657d030a8a 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AllFlowSummaries.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import AmbiguousCoreMethods private import Arrays private import AsyncAwait diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll index 45ad9cf7a9c9..4e1c9ee6884e 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AmbiguousCoreMethods.qll @@ -20,6 +20,8 @@ * * (Promise is absent in the table above as there currently are no name clashes with Promise methods) */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll index 6754d3db3071..1196ffdbac9c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Arrays.qll @@ -3,6 +3,8 @@ * * Note that some of Array methods are modeled in `AmbiguousCoreMethods.qll`, and `toString` is special-cased elsewhere. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll index 246ac0f19d08..6a33c9a5c4fb 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/AsyncAwait.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow through `async` functions and the `await` operator. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll index 2866c8926087..80e43fdfcd8c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Decoders.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.FlowSummary private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll index 2976b4673150..2661802b97e5 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/DynamicImportStep.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow from a module into a dynamic `import()` expression. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll index 252baab207bb..3dff015d9f37 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ExceptionFlow.qll @@ -1,6 +1,8 @@ /** * Contains a summary for propagating exceptions out of callbacks */ +overlay[local?] +module; private import javascript private import FlowSummaryUtil diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll index 33f891935f42..290567efbd9d 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/FlowSummaryUtil.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.FlowSummary private import semmle.javascript.dataflow.internal.Contents::Private diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll index ecc84170026f..d8460f7d729a 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/ForOfLoops.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow through `for..of` loops. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode @@ -48,12 +50,18 @@ class ForOfLoopStep extends AdditionalFlowInternal { ) { exists(ForOfStmt stmt | pred = getSynthesizedNode(stmt, "for-of-map-key") and - contents.asSingleton().asArrayIndex() = 0 + contents = arrayIndex0() or pred = getSynthesizedNode(stmt, "for-of-map-value") and - contents.asSingleton().asArrayIndex() = 1 + contents = arrayIndex1() | succ = DataFlow::lvalueNode(stmt.getLValue()) ) } } + +pragma[nomagic] +private DataFlow::ContentSet arrayIndex0() { result.asSingleton().asArrayIndex() = 0 } + +pragma[nomagic] +private DataFlow::ContentSet arrayIndex1() { result.asSingleton().asArrayIndex() = 1 } diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll index 75815d00341d..4f0868db5196 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Generators.qll @@ -1,6 +1,8 @@ /** * Contains flow steps to model flow through generator functions. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll index 6b1a182a49bd..7f9c13c63dfd 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Iterators.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through iterators. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.internal.DataFlowNode diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll index ecd2dcdfc79b..4b8ecdeb4f28 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/JsonStringify.qll @@ -1,6 +1,8 @@ /** * Contains implicit read steps at the input to any function that converts a deep object to a string, such as `JSON.stringify`. */ +overlay[local?] +module; private import javascript private import FlowSummaryUtil diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll index d9649d407c61..645e36941dc3 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Maps.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through `Map` objects. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll index 74048f0e397e..10292958df2f 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Promises.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through `Promise` objects. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll index 6b4f089b38ec..e4d0951764f1 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Sets.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through `Set` objects. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll index bf9442219a75..b5ecc8ef603c 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/Strings.qll @@ -1,6 +1,8 @@ /** * Contains flow summaries and steps modeling flow through string methods. */ +overlay[local?] +module; private import javascript private import semmle.javascript.dataflow.FlowSummary diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll index 19a28036db49..0ac2307c81a5 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/TypedArrays.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.dataflow.FlowSummary private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll index 0a47b6fcf9f5..3d8d88d8ae47 100644 --- a/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll +++ b/javascript/ql/lib/semmle/javascript/internal/flow_summaries/UrlSearchParams.qll @@ -3,6 +3,8 @@ * * For now, the `URLSearchParams` object is modeled as a `Map` object. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll b/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll index dc90dcc39469..d926e118ae64 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/JSPaths.qll @@ -2,6 +2,8 @@ * Provides predicates for use in `Folder::ResolveSig` in order to resolve * paths using JavaScript semantics. */ +overlay[local?] +module; private import javascript private import semmle.javascript.TSConfig diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll index 5f4a6eb930ea..4bbf3b6f62b6 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PackageJsonEx.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.internal.paths.JSPaths diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll index ad5552ce78c3..bc29ab168478 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathConcatenation.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript /** diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll index 63ffd9554773..65666d7f7f4d 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathExprResolver.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private import semmle.javascript.internal.paths.PackageJsonEx private import semmle.javascript.internal.paths.JSPaths diff --git a/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll b/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll index d3da0a51cfa3..12f1ecf01fd6 100644 --- a/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll +++ b/javascript/ql/lib/semmle/javascript/internal/paths/PathMapping.qll @@ -1,6 +1,8 @@ /** * Provides an extensible mechanism for modeling path mappings. */ +overlay[local?] +module; private import javascript private import semmle.javascript.TSConfig diff --git a/javascript/ql/lib/semmle/javascript/linters/ESLint.qll b/javascript/ql/lib/semmle/javascript/linters/ESLint.qll index acc52a5d6b51..96a5fd22cf73 100644 --- a/javascript/ql/lib/semmle/javascript/linters/ESLint.qll +++ b/javascript/ql/lib/semmle/javascript/linters/ESLint.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with ESLint directives and configurations. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/linters/JSLint.qll b/javascript/ql/lib/semmle/javascript/linters/JSLint.qll index d03ecb2abf9b..108010db5631 100644 --- a/javascript/ql/lib/semmle/javascript/linters/JSLint.qll +++ b/javascript/ql/lib/semmle/javascript/linters/JSLint.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with JSLint/JSHint directives. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/linters/Linting.qll b/javascript/ql/lib/semmle/javascript/linters/Linting.qll index 887467010457..f86dae076fb8 100644 --- a/javascript/ql/lib/semmle/javascript/linters/Linting.qll +++ b/javascript/ql/lib/semmle/javascript/linters/Linting.qll @@ -1,6 +1,8 @@ /** * Provides classes for working with various JavaScript linters. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll b/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll index 0bc4f32d4bc1..ba674b836c7e 100644 --- a/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll +++ b/javascript/ql/lib/semmle/javascript/meta/ExtractionMetrics.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + import javascript /** diff --git a/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll b/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll index 52e1e0d00f38..8227cfef6f4d 100644 --- a/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll +++ b/javascript/ql/lib/semmle/javascript/security/CommonFlowState.qll @@ -1,6 +1,8 @@ /** * Contains a class with flow states that are used by multiple queries. */ +overlay[local?] +module; private import javascript private import TaintedUrlSuffixCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll index aed0e26a6b3f..9fcf5d380a12 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll @@ -3,6 +3,8 @@ * overly permissive CORS configurations, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll index 03d20578b0e1..8f0fd1152292 100644 --- a/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationQuery.qll @@ -7,6 +7,8 @@ * otherwise `CorsPermissiveConfigurationCustomizations` should * be imported instead. */ +overlay[local?] +module; import javascript import CorsPermissiveConfigurationCustomizations::CorsPermissiveConfiguration diff --git a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll index 13a03a3bd888..cdd2414f15a5 100644 --- a/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll +++ b/javascript/ql/lib/semmle/javascript/security/CryptoAlgorithms.qll @@ -1,5 +1,7 @@ /** * Provides classes modeling cryptographic algorithms, separated into strong and weak variants. */ +overlay[local?] +module; import codeql.concepts.CryptoAlgorithms diff --git a/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll b/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll index f837c710fd46..661996223e12 100644 --- a/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll +++ b/javascript/ql/lib/semmle/javascript/security/FunctionalityFromUntrustedSource.qll @@ -1,6 +1,8 @@ /** * Provides classes for finding functionality that is loaded from untrusted sources and used in script or frame elements. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll index 13d5033458af..87fe5d164cdd 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteBlacklistSanitizer.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates for working with incomplete blacklist sanitizers. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll index 2a2d4d4d6014..2b275421cc17 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationQuery.qll @@ -1,6 +1,8 @@ /** * Provides shared predicates for reasoning about improper multi-character sanitization. */ +overlay[local?] +module; import IncompleteMultiCharacterSanitizationSpecific diff --git a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll index 10d9ab19f983..b21074fa990e 100644 --- a/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/IncompleteMultiCharacterSanitizationSpecific.qll @@ -1,6 +1,8 @@ /** * Provides language-specific predicates for reasoning about improper multi-character sanitization. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.regexp.RegExpTreeView::RegExpTreeView as TreeView diff --git a/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll index 183fca296c76..e89e2850871d 100644 --- a/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/PasswordInConfigurationFileQuery.qll @@ -1,4 +1,6 @@ /** Classses and predicates for reasoning about passwords in configuration files. */ +overlay[local?] +module; import javascript import semmle.javascript.RestrictedLocations diff --git a/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll b/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll index 05a6fbc17d46..c6bd19c10b84 100644 --- a/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll +++ b/javascript/ql/lib/semmle/javascript/security/SensitiveActions.qll @@ -8,6 +8,8 @@ * In addition, there are methods that ought not to be executed or not in a fashion that the user * can control. This includes authorization methods such as logins, and sending of data, etc. */ +overlay[local?] +module; import javascript import codeql.concepts.internal.SensitiveDataHeuristics diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll b/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll index a300291ae9cd..9521550d9b9e 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedObject.qll @@ -12,6 +12,8 @@ * 3. The flow steps from `TaintedObject::isAdditionalFlowStep`. * 4. The barriers from `TaintedObject::SanitizerGuard::getABarrierNode(state)`. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll index 5dc687deecae..509622b80276 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedObjectCustomizations.qll @@ -2,6 +2,8 @@ * Provides access to the "tainted object" flow label defined in `TaintedObject.qll`, without * materializing that flow label. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll index 1d4ff0c4b7fe..de256d95296f 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffix.qll @@ -2,6 +2,8 @@ * Provides a flow label for reasoning about URLs with a tainted query and fragment part, * which we collectively refer to as the "suffix" of the URL. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll index 841f830f2bf9..7b6ea30c0e32 100644 --- a/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/TaintedUrlSuffixCustomizations.qll @@ -2,6 +2,8 @@ * Provides a flow state for reasoning about URLs with a tainted query and fragment part, * which we collectively refer to as the "suffix" of the URL. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.internal.DataFlowPrivate as DataFlowPrivate diff --git a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll index e66200370dd6..b413ecd253db 100644 --- a/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll +++ b/javascript/ql/lib/semmle/javascript/security/UselessUseOfCat.qll @@ -1,6 +1,8 @@ /** * Provides predicates and classes for working with useless uses of the unix command `cat`. */ +overlay[local?] +module; import javascript import Expressions.ExprHasNoEffect diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll index e0db75ab52c0..93310a41ff66 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/BrokenCryptoAlgorithmCustomizations.qll @@ -3,6 +3,8 @@ * sensitive information in broken or weak cryptographic algorithms, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll index 70641af0286a..03ad511b1eee 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/BuildArtifactLeakCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sinks for reasoning about storage of sensitive information * in build artifact, as well as extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll index a7bbc73ce038..0924beccf8ac 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextLoggingCustomizations.qll @@ -3,6 +3,8 @@ * clear-text logging of sensitive information, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll index 1d57fdb50fd0..53e9eeb870f4 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CleartextStorageCustomizations.qll @@ -3,6 +3,8 @@ * cleartext storage of sensitive information, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll index 1b987ea2679e..4ada245d1aec 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll @@ -3,6 +3,8 @@ * unvalidated URL redirection problems on the client side, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedUrlSuffixCustomizations @@ -63,6 +65,7 @@ module ClientSideUrlRedirect { /** * Holds if `node` extracts a part of a URL that does not contain the suffix. */ + overlay[caller?] pragma[inline] deprecated predicate isPrefixExtraction(DataFlow::MethodCallNode node) { // Block flow through prefix-extraction `substring(0, ...)` and `split("#")[0]` diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll index 526eaf1be361..ac7c9b89b450 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectQuery.qll @@ -6,6 +6,8 @@ * `ClientSideUrlRedirect::Configuration` is needed, otherwise * `ClientSideUrlRedirectCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import UrlConcatenation diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll index 8fded55bc896..e1c38ad3c4c2 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll @@ -3,6 +3,8 @@ * code injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll index 9762c1142b99..449aa17cb51a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll @@ -3,6 +3,8 @@ * command-injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll index 034699cee0d5..18b32f90aeb9 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ConditionalBypassCustomizations.qll @@ -3,6 +3,8 @@ * bypass of sensitive action guards, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll index eaf78fd4c4c9..b615cef87254 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/CorsMisconfigurationForCredentialsCustomizations.qll @@ -3,6 +3,8 @@ * CORS misconfiguration for credentials transfer, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll index f959de6c0b5e..7ead4652939e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DOM.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about DOM types and methods. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll index eaac474b2074..58f1229355df 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionCustomizations.qll @@ -2,6 +2,8 @@ * Provides sources, sinks and sanitizers for reasoning about * DoS attacks due to inefficient handling of user-controlled objects. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedObjectCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll index ad03ad93b949..83f3ac652c8d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DeepObjectResourceExhaustionQuery.qll @@ -2,6 +2,8 @@ * Provides a taint tracking configuration for reasoning about DoS attacks * due to inefficient handling of user-controlled objects. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll index 5be7082137a9..6ac787b078ab 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DifferentKindsComparisonBypassCustomizations.qll @@ -3,6 +3,8 @@ * comparisons that relies on different kinds of HTTP request data, as * well as extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll index 1440fb5539d7..571b3456c051 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources for reasoning about DOM-based * cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll index 36d5b3ba0a6b..5bb0614147b6 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/DomBasedXssQuery.qll @@ -2,6 +2,8 @@ * Provides a taint-tracking configuration for reasoning about DOM-based * cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedUrlSuffix diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll index 70281110a5fb..cf556d06e3eb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssCustomizations.qll @@ -3,6 +3,8 @@ * cross-site scripting vulnerabilities where the taint-flow passes through a thrown * exception. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll index d7f4fe954f9c..4d2de67fe7d0 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExceptionXssQuery.qll @@ -3,6 +3,8 @@ * scripting vulnerabilities where the taint-flow passes through a thrown * exception. */ +overlay[local?] +module; import javascript import DomBasedXssCustomizations::DomBasedXss as DomBasedXssCustom diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll index f59c7b78e367..e97f65e02318 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ExternalAPIUsedWithUntrustedDataCustomizations.qll @@ -2,6 +2,8 @@ * Provides sources, sinks and sanitizers for reasoning about flow of * untrusted data into an external API. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll index 8fac31ddf54d..d94c1bac78a2 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/FileAccessToHttpCustomizations.qll @@ -3,6 +3,8 @@ * file data in outbound network requests, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll index 8bd9b290fc6b..303a6995af7c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedCredentialsCustomizations.qll @@ -3,6 +3,8 @@ * hardcoded credentials, as well as extension points for adding your * own. */ +overlay[local?] +module; import semmle.javascript.filters.ClassifyFiles import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll index 9ec6f2d5b4ad..42f4ec66b5cf 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeCustomizations.qll @@ -3,6 +3,8 @@ * hard-coded data being interpreted as code, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.dataflow.CodeInjectionCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll index 0d33ee11876f..925fff311f01 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HardcodedDataInterpretedAsCodeQuery.qll @@ -7,6 +7,8 @@ * otherwise `HardcodedDataInterpretedAsCodeCustomizations` should be * imported instead. */ +overlay[local?] +module; import javascript import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsCode diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll index 46823c990ef7..6494e553093c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessCustomizations.qll @@ -3,6 +3,8 @@ * writing user-controlled data to files, as well as extension points * for adding your own. */ +overlay[local?] +module; /** * Provides default sources, sinks and sanitizers for reasoning about diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll index 2b44de07a4c3..c35682bc3e35 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/HttpToFileAccessSpecific.qll @@ -1,6 +1,8 @@ /** * Provides imports and classes needed for `HttpToFileAccessQuery` and `HttpToFileAccessCustomizations`. */ +overlay[local?] +module; import javascript private import HttpToFileAccessCustomizations::HttpToFileAccess diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll index 4bf212b90d2a..493fd2b8e7de 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ImproperCodeSanitizationCustomizations.qll @@ -3,6 +3,8 @@ * improper code sanitization, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll index f421a92298f9..864447d6ffca 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationCustomizations.qll @@ -3,6 +3,8 @@ * incomplete HTML sanitization vulnerabilities, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.IncompleteBlacklistSanitizer diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll index 578c15635bbb..979d610ccc5e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IncompleteHtmlAttributeSanitizationQuery.qll @@ -6,6 +6,8 @@ * `IncompleteHtmlAttributeSanitization::Configuration` is needed, otherwise * `IncompleteHtmlAttributeSanitizationCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import IncompleteHtmlAttributeSanitizationCustomizations::IncompleteHtmlAttributeSanitization diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll index 6d6c9c3d75fa..fc4bfd3d0eed 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandArgument.qll @@ -1,6 +1,8 @@ /** * Provides predicates for reasoning about indirect command arguments. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll index 84c4600fbc03..3a6418c3aa9f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/IndirectCommandInjectionCustomizations.qll @@ -3,6 +3,8 @@ * command-injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll index c7acce602b72..ffe1ae2c19e4 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadCustomizations.qll @@ -3,6 +3,8 @@ * download of sensitive file through insecure connection, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll index ffcfead78961..07d11e282ff1 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureDownloadQuery.qll @@ -5,6 +5,8 @@ * `InsecureDownload::Configuration` is needed, otherwise * `InsecureDownloadCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import InsecureDownloadCustomizations::InsecureDownload diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll index d40e3a510c76..731cd55ed55c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureRandomnessCustomizations.qll @@ -3,6 +3,8 @@ * random values that are not cryptographically secure, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll index 216482947aba..270158216dbb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsecureTemporaryFileCustomizations.qll @@ -3,6 +3,8 @@ * insecure temporary file creation, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll index 8901be9962f8..830fe27b8860 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/InsufficientPasswordHashCustomizations.qll @@ -3,6 +3,8 @@ * password hashing with insufficient computational effort, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll index 63da6fca1054..9e6454fabdf8 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionCustomizations.qll @@ -3,6 +3,8 @@ * DoS attacks using objects with unbounded length property, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll index 522df62eca56..f0b7090d8436 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/LoopBoundInjectionQuery.qll @@ -6,6 +6,8 @@ * `LoopBoundInjection::Configuration` is needed, otherwise * `LoopBoundInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import LoopBoundInjectionCustomizations::LoopBoundInjection diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll index 5f4ad1b3d73e..9a914c1ab296 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/MissingRateLimiting.qll @@ -21,6 +21,8 @@ * For `RateLimitedRouteHandlerExpr`, the default subclasses model popular npm packages; * other means of rate-limiting can be supported by adding more subclasses. */ +overlay[local?] +module; import javascript private import semmle.javascript.frameworks.ConnectExpressShared::ConnectExpressShared diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll index 36c0601d501c..901087cb422f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionCustomizations.qll @@ -3,6 +3,8 @@ * NoSQL injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll index e7d93aabb977..1316762e64b7 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/NosqlInjectionQuery.qll @@ -6,6 +6,8 @@ * `NosqlInjection::Configuration` is needed, otherwise * `NosqlInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll index 62f87e29b0b9..df71e655b9db 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PostMessageStarCustomizations.qll @@ -3,6 +3,8 @@ * cross-window communication with unrestricted origin, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.SensitiveActions::HeuristicNames diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll index 81770b95a02e..285c840c3856 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PropertyInjectionShared.qll @@ -2,6 +2,8 @@ * Provides predicates for reasoning about flow of user-controlled values that are used * as property names. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll index bb2f9739501c..6be49fbd671f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll @@ -2,6 +2,8 @@ * Provides sources, sinks, and sanitizers for reasoning about assignments * that my cause prototype pollution. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll index 96eed4cadc2b..e0a9e5844402 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll @@ -6,6 +6,8 @@ * `PrototypePollutingAssignment::Configuration` is needed, otherwise * `PrototypePollutingAssignmentCustomizations` should be imported instead. */ +overlay[local?] +module; private import javascript private import semmle.javascript.DynamicPropertyAccess diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll index 1e95e4b550fb..4c429c4c0cb7 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionCustomizations.qll @@ -3,6 +3,8 @@ * user-controlled objects flowing into a vulnerable `extends` call, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll index 86fbb1273d97..d39aa9ec4e55 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutionQuery.qll @@ -6,6 +6,8 @@ * `PrototypePollution::Configuration` is needed, otherwise * `PrototypePollutionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import semmle.javascript.security.TaintedObject diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll index 70b2685d90d4..14f8f7fef4b6 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ReflectedXssCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources for reasoning about reflected * cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll index 5ee39219d260..5a972629ef91 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RegExpInjectionCustomizations.qll @@ -3,6 +3,8 @@ * untrusted user input used to construct regular expressions, as well * as extension points for adding your own. */ +overlay[local?] +module; import javascript private import codeql.threatmodels.ThreatModels diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll index 58600c579a84..9f4975e605ae 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemoteFlowSources.qll @@ -114,6 +114,7 @@ class ClientSideRemoteFlowKind extends string { * `name` and `address` of global variable `user` should be considered as remote flow sources with * source type "user input". */ +overlay[local?] private class RemoteFlowSourceAccessPath extends JsonString { string sourceType; @@ -167,6 +168,7 @@ private class RemoteFlowSourceAccessPath extends JsonString { * The global variable referenced by a `RemoteFlowSourceAccessPath`, declared as an API * entry point. */ +overlay[local?] private class ExternalRemoteFlowSourceSpecEntryPoint extends API::EntryPoint { string name; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll index 6157671e6a91..a1c5ee26631c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RemotePropertyInjectionCustomizations.qll @@ -4,6 +4,8 @@ * property, into a header or for calling an object's method, as well * as extension points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll index ec46ef91c3c0..dda51bcca412 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/RequestForgeryCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources, sinks and sanitizers for reasoning about * request forgery, as well as extension points for adding your own. */ +overlay[local?] +module; import semmle.javascript.security.dataflow.RemoteFlowSources diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll index e24de9f4d6f9..da333d36b2af 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ResourceExhaustionCustomizations.qll @@ -3,6 +3,8 @@ * resource exhaustion vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll index 416ad56bef16..c9e8eef77b53 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionCustomizations.qll @@ -3,6 +3,8 @@ * second order command injection, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.PackageExports as Exports @@ -129,6 +131,7 @@ module SecondOrderCommandInjection { /** * A sink that invokes a command described by the `VulnerableCommand` class. */ + overlay[global] abstract class VulnerableCommandSink extends Sink { VulnerableCommand cmd; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll index 0c5af5abd37c..5d6a35ce4602 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SecondOrderCommandInjectionQuery.qll @@ -6,6 +6,8 @@ * `SecondOrderCommandInjection::Configuration` is needed, otherwise * `SecondOrderCommandInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import SecondOrderCommandInjectionCustomizations::SecondOrderCommandInjection diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll index 55815717e98c..22e377d59164 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ServerSideUrlRedirectCustomizations.qll @@ -3,6 +3,8 @@ * unvalidated URL redirection problems on the server side, as well as * extension points for adding your own. */ +overlay[local?] +module; import javascript import RemoteFlowSources diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll index 87d7d340afd1..5d732bd3921e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll @@ -3,6 +3,8 @@ * command-injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.TaintedPathCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll index 8afb65519ad4..7c140061758f 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/SqlInjectionCustomizations.qll @@ -3,6 +3,8 @@ * string based query injection vulnerabilities, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll index 205c00f8f795..4ea1570012fc 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/StackTraceExposureCustomizations.qll @@ -3,6 +3,8 @@ * stack trace exposure vulnerabilities, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll index 412332b54115..5b213d590e8e 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/StoredXssCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources, sinks and sanitizers for reasoning about * stored cross-site scripting vulnerabilities. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll index ec94277235cd..28b7c6534abc 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources, sinks and sanitizers for reasoning about * format injections, as well as extension points for adding your own. */ +overlay[local?] +module; /** * Provides default sources, sinks and sanitizers for reasoning about diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll index e2a28a68baf7..69b4488ef816 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedFormatStringSpecific.qll @@ -1,6 +1,8 @@ /** * Provides JS-specific imports needed for `TaintedFormatStringQuery` and `TaintedFormatStringCustomizations`. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll index f863b86a3b57..70eb1a56fbab 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathCustomizations.qll @@ -3,6 +3,8 @@ * tainted-path vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript @@ -194,6 +196,7 @@ module TaintedPath { * There are currently four flow labels, representing the different combinations of * normalization and absoluteness. */ + overlay[global] abstract class PosixPath extends DataFlow::FlowLabel { Normalization normalization; Relativeness relativeness; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll index 8b50a69cedce..89a32bb0e434 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TaintedPathQuery.qll @@ -6,6 +6,8 @@ * `TaintedPath::Configuration` is needed, otherwise * `TaintedPathCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript private import TaintedPathCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll index b141feb1409f..e1d1051eb40d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionCustomizations.qll @@ -3,6 +3,8 @@ * template object injection vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.TaintedObjectCustomizations diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll index 348e59937b5e..667d59526747 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TemplateObjectInjectionQuery.qll @@ -6,6 +6,8 @@ * `TemplateObjectInjection::Configuration` is needed, otherwise * `TemplateObjectInjectionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import TemplateObjectInjectionCustomizations::TemplateObjectInjection diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll index de09aedce124..415de1671cb5 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/TypeConfusionThroughParameterTamperingCustomizations.qll @@ -3,6 +3,8 @@ * type confusion for HTTP request inputs, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll index e29d5d87a70f..365c61fe96f6 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstruction.qll @@ -6,6 +6,8 @@ * `UnsafeCodeConstruction::Configuration` is needed, otherwise * `UnsafeCodeConstructionCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll index 95454df7743f..6ec98bd918a7 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeCodeConstructionCustomizations.qll @@ -3,6 +3,8 @@ * constructed from library input vulnerabilities, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll index 2e13e0ee7f9b..3e54a28fd54b 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDeserializationCustomizations.qll @@ -3,6 +3,8 @@ * unsafe deserialization, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll index 756efb5f3fb6..5afc78aa0ad9 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessCustomizations.qll @@ -4,6 +4,8 @@ * with unsafe methods, as well as extension points for adding your * own. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll index 423b50f17f70..4f2915998dd3 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeDynamicMethodAccessQuery.qll @@ -6,6 +6,8 @@ * `UnsafeDynamicMethodAccess::Configuration` is needed, otherwise * `UnsafeDynamicMethodAccessCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import PropertyInjectionShared diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll index 06bad34b80c4..b3641e9ba0d4 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionCustomizations.qll @@ -3,6 +3,8 @@ * unsafe HTML constructed from library input, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript @@ -101,6 +103,7 @@ module UnsafeHtmlConstruction { * A sink for `js/html-constructed-from-input` that constructs some HTML where * that HTML is later used in `xssSink`. */ + overlay[global] abstract class XssSink extends Sink { DomBasedXss::Sink xssSink; diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll index 913329813c1b..be797637b364 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeHtmlConstructionQuery.qll @@ -2,6 +2,8 @@ * Provides a taint-tracking configuration for reasoning about * unsafe HTML constructed from library input vulnerabilities. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.dataflow.DomBasedXssCustomizations::DomBasedXss as DomBasedXss diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll index 3fb2827707e3..fe5e15353ab9 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeJQueryPluginCustomizations.qll @@ -3,6 +3,8 @@ * unsafe jQuery plugins, as well as extension points for adding your * own. */ +overlay[local?] +module; import javascript private import semmle.javascript.dataflow.InferredTypes diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll index e65fac9530d7..de19940625ba 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnsafeShellCommandConstructionCustomizations.qll @@ -3,6 +3,8 @@ * shell command constructed from library input vulnerabilities, * as well as extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.PackageExports as Exports diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll index e516167a30b4..7fedd47a566a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallCustomizations.qll @@ -3,6 +3,8 @@ * unvalidated dynamic method calls, as well as extension points for * adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll index 7b6a6124edaf..e0316f20a32d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UnvalidatedDynamicMethodCallQuery.qll @@ -7,6 +7,8 @@ * `UnvalidatedDynamicMethodCallCustomizations` should be imported * instead. */ +overlay[local?] +module; import javascript import semmle.javascript.frameworks.Express diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll index 81b7be46cb26..0e79dbb73efb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/UrlConcatenation.qll @@ -3,6 +3,8 @@ * the characters `?` and `#`, which are considered sanitizers for * the URL redirection queries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll index 15ba3e2a17d2..b2e86624851a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XmlBombCustomizations.qll @@ -3,6 +3,8 @@ * XML-bomb vulnerabilities, as well as extension points for adding * your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll index 6eb3f12d16ad..dc47c919339c 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XpathInjectionCustomizations.qll @@ -3,6 +3,8 @@ * untrusted user input used in XPath expression, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll index f139ccc48dbb..123cb3fb2513 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/Xss.qll @@ -1,6 +1,8 @@ /** * Provides classes and predicates used by the XSS queries. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll index 865324ed8d5b..3e443266caaa 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XssThroughDomCustomizations.qll @@ -2,6 +2,8 @@ * Provides default sources for reasoning about * cross-site scripting vulnerabilities through the DOM. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll index 9f6fe305bdf9..5a6454d6775a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/XxeCustomizations.qll @@ -3,6 +3,8 @@ * XML External Entity (XXE) vulnerabilities, as well as extension * points for adding your own. */ +overlay[local?] +module; import javascript import semmle.javascript.security.dataflow.DOM diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll index 01e40fd5dbf5..91443624f464 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipCustomizations.qll @@ -3,6 +3,8 @@ * unsafe zip and tar archive extraction, as well as extension points * for adding your own. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll index b59a78462b8c..3a235e9ac0eb 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/ZipSlipQuery.qll @@ -6,6 +6,8 @@ * `ZipSlip::Configuration` is needed, otherwise * `ZipSlipCustomizations` should be imported instead. */ +overlay[local?] +module; import javascript import ZipSlipCustomizations::ZipSlip diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll b/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll index c9853ce35f18..6c63fbbcb67b 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/HostnameRegexp.qll @@ -2,6 +2,8 @@ * Provides predicates for reasoning about regular expressions * that match URLs and hostname patterns. */ +overlay[local?] +module; private import javascript as JS private import semmle.javascript.security.regexp.RegExpTreeView::RegExpTreeView as TreeImpl diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll index dce63894f8b4..6e6877ce8168 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/PolynomialReDoSCustomizations.qll @@ -3,6 +3,8 @@ * polynomial regular expression denial-of-service attacks, as well * as extension points for adding your own. */ +overlay[local?] +module; import javascript private import semmle.javascript.security.regexp.RegExpTreeView::RegExpTreeView as TreeView diff --git a/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll b/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll index e5aa0e490fa9..d0032e0489c4 100644 --- a/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll +++ b/javascript/ql/lib/semmle/javascript/security/regexp/RegExpTreeView.qll @@ -1,6 +1,8 @@ /** * Provides JavaScript-specific definitions for use in the NfaUtils module. */ +overlay[local?] +module; private import codeql.regex.nfa.NfaUtils as NfaUtils private import codeql.regex.RegexTreeView diff --git a/javascript/ql/lib/utils/test/ConsistencyChecking.qll b/javascript/ql/lib/utils/test/ConsistencyChecking.qll index f614a93500d7..8b87537db083 100644 --- a/javascript/ql/lib/utils/test/ConsistencyChecking.qll +++ b/javascript/ql/lib/utils/test/ConsistencyChecking.qll @@ -3,6 +3,8 @@ * * Will be replaced with standardized inline test expectations in the future. */ +overlay[local?] +module; import javascript diff --git a/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll b/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll index 4072e4dd9e6b..11e81f40ed15 100644 --- a/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll +++ b/javascript/ql/lib/utils/test/InlineFlowTestUtil.qll @@ -4,6 +4,8 @@ * We reuse these predicates in some type-tracking tests that don't wish to bring in the * test configuration from `InlineFlowTest`. */ +overlay[local?] +module; private import javascript diff --git a/javascript/ql/lib/utils/test/InlineSummaries.qll b/javascript/ql/lib/utils/test/InlineSummaries.qll index 559f13609778..87f58f91f65d 100644 --- a/javascript/ql/lib/utils/test/InlineSummaries.qll +++ b/javascript/ql/lib/utils/test/InlineSummaries.qll @@ -1,6 +1,10 @@ +overlay[local?] +module; + import javascript import semmle.javascript.dataflow.FlowSummary +overlay[local] class MkSummary extends SummarizedCallable { private CallExpr mkSummary; diff --git a/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll b/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll index 0995d06199c2..457da8000c53 100644 --- a/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll +++ b/javascript/ql/lib/utils/test/LegacyDataFlowDiff.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript private signature class LegacyConfigSig { diff --git a/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll b/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll index 42eb94230ae6..feea08bf9f8f 100644 --- a/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll +++ b/javascript/ql/lib/utils/test/internal/InlineExpectationsTestImpl.qll @@ -1,3 +1,6 @@ +overlay[local?] +module; + private import javascript as JS private import codeql.util.test.InlineExpectationsTest diff --git a/javascript/ql/src/Expressions/DuplicateProperty.ql b/javascript/ql/src/Expressions/DuplicateProperty.ql index febdfe5b8826..b13f1a93ec0d 100644 --- a/javascript/ql/src/Expressions/DuplicateProperty.ql +++ b/javascript/ql/src/Expressions/DuplicateProperty.ql @@ -14,12 +14,26 @@ import Clones +bindingset[init] +pragma[inline_late] +private Property getPropertyFromInitializerStrict(Expr init) { result.getInit() = init } + +pragma[nomagic] +private predicate duplicateProperties( + DuplicatePropertyInitDetector dup, Property prop1, Property prop2 +) { + exists(Expr init2 | + dup.same(init2) and + prop1 = getPropertyFromInitializerStrict(dup) and + prop2 = getPropertyFromInitializerStrict(init2) + ) +} + from ObjectExpr oe, int i, int j, Property p, Property q, DuplicatePropertyInitDetector dpid where + duplicateProperties(dpid, p, q) and p = oe.getProperty(i) and q = oe.getProperty(j) and - dpid = p.getInit() and - dpid.same(q.getInit()) and i < j and // only report the next duplicate not exists(int mid | mid in [i + 1 .. j - 1] | dpid.same(oe.getProperty(mid).getInit())) diff --git a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql index 3502c0ea5561..89ab2f3f9449 100644 --- a/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql +++ b/javascript/ql/test/ApiGraphs/custom-entry-point/VerifyAssertions.ql @@ -1,3 +1,4 @@ +overlay[local?] class CustomEntryPoint extends API::EntryPoint { CustomEntryPoint() { this = "CustomEntryPoint" } diff --git a/javascript/ql/test/library-tests/AMD/tests.ql b/javascript/ql/test/library-tests/AMD/tests.ql index e71ae089f2d4..150c5e9a294d 100644 --- a/javascript/ql/test/library-tests/AMD/tests.ql +++ b/javascript/ql/test/library-tests/AMD/tests.ql @@ -1,5 +1,6 @@ import javascript +overlay[local] class TestAmdModuleRange extends AmdModuleDefinition::Range { TestAmdModuleRange() { this.getCallee().(PropAccess).getQualifiedName() = "test.amd.range" } } diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql index a2d69f55ce82..c0571921fba8 100644 --- a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitions.ql @@ -4,6 +4,7 @@ import semmle.javascript.dataflow.internal.FlowSteps as FlowSteps import semmle.javascript.dataflow.internal.AbstractPropertiesImpl as AbstractPropertiesImpl import semmle.javascript.dataflow.CustomAbstractValueDefinitions +overlay[local] class MyCustomAbstractValueDefinition extends CustomAbstractValueDefinition { DataFlow::ValueNode node; diff --git a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql index 0308ad6bf455..0f34b14b48c5 100644 --- a/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql +++ b/javascript/ql/test/library-tests/CustomAbstractValueDefinitions/CustomAbstractValueDefinitionsFlow.ql @@ -2,6 +2,7 @@ import javascript import semmle.javascript.dataflow.InferredTypes import semmle.javascript.dataflow.CustomAbstractValueDefinitions +overlay[local] class MyCustomAbstractValueDefinition extends CustomAbstractValueDefinition, AST::ValueNode { MyCustomAbstractValueDefinition() { this.flow() instanceof DataFlow::ObjectLiteralNode and diff --git a/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql b/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql index 0b3f87f1b8d2..75c4af21ed74 100644 --- a/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql +++ b/javascript/ql/test/library-tests/FlowCustomisation/customValues.ql @@ -4,6 +4,7 @@ private import semmle.javascript.dataflow.InferredTypes /** * A custom abstract value representing the DOM object `document`. */ +overlay[local] class Document extends CustomAbstractValueTag { Document() { this = "document" } @@ -25,6 +26,7 @@ class Document extends CustomAbstractValueTag { * Note that `getType()` isn't quite right, since `typeof document.all === 'undefined'`, * but that's fine for the purposes of this test. */ +overlay[local] class DocumentAll extends CustomAbstractValueTag { DocumentAll() { this = "document.all" } diff --git a/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql b/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql index abc8c4e17555..c118e36e6067 100644 --- a/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql +++ b/javascript/ql/test/library-tests/ModuleImportNodes/CustomImport.ql @@ -1,5 +1,6 @@ import javascript +overlay[local] class CustomImport extends DataFlow::ModuleImportNode::Range, DataFlow::CallNode { CustomImport() { this.getCalleeName() = "customImport" } diff --git a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql index 9a5350948fe2..a9d27450aee4 100644 --- a/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql +++ b/javascript/ql/test/library-tests/RecursionPrevention/SourceNodeFlowsTo.ql @@ -7,6 +7,7 @@ import javascript +overlay[local] class BadSourceNode extends DataFlow::SourceNode { BadSourceNode() { this.(DataFlow::PropRead).getPropertyName() = "foo" } diff --git a/javascript/ql/test/library-tests/frameworks/data/test.ql b/javascript/ql/test/library-tests/frameworks/data/test.ql index 6a1d571351b4..6ba504e921fa 100644 --- a/javascript/ql/test/library-tests/frameworks/data/test.ql +++ b/javascript/ql/test/library-tests/frameworks/data/test.ql @@ -2,6 +2,7 @@ import javascript deprecated import utils.test.ConsistencyChecking import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels +overlay[local] class TypeModelFromCodeQL extends ModelInput::TypeModel { override predicate isTypeUsed(string type) { type = "danger-constant" } diff --git a/javascript/ql/test/library-tests/frameworks/data/warnings.ql b/javascript/ql/test/library-tests/frameworks/data/warnings.ql index 1ede8e08bcc2..2c3c044ef694 100644 --- a/javascript/ql/test/library-tests/frameworks/data/warnings.ql +++ b/javascript/ql/test/library-tests/frameworks/data/warnings.ql @@ -1,6 +1,7 @@ import javascript import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels +overlay[local] class IsTesting extends ApiGraphModels::TestAllModels { IsTesting() { this = this } } diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll index c04a85487acf..80ec45a3cf17 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModels.qll @@ -62,6 +62,8 @@ * should be prefixed with a tilde character (`~`). For example, `~Bar` can be used to indicate that * the type is not intended to match a static type. */ +overlay[local?] +module; private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific diff --git a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll index 4969da43be34..3f38c498f324 100644 --- a/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll +++ b/python/ql/lib/semmle/python/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -1,6 +1,8 @@ /** * Defines extensible predicates for contributing library models from data extensions. */ +overlay[local] +module; /** * Holds if the value at `(type, path)` should be seen as a flow diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll index c04a85487acf..80ec45a3cf17 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll @@ -62,6 +62,8 @@ * should be prefixed with a tilde character (`~`). For example, `~Bar` can be used to indicate that * the type is not intended to match a static type. */ +overlay[local?] +module; private import codeql.util.Unit private import ApiGraphModelsSpecific as Specific diff --git a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll index 4969da43be34..3f38c498f324 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsExtensions.qll @@ -1,6 +1,8 @@ /** * Defines extensible predicates for contributing library models from data extensions. */ +overlay[local] +module; /** * Holds if the value at `(type, path)` should be seen as a flow