这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
23e42c8
JS: Overlay annotations for AST layer
asgerf Aug 29, 2025
2b338fc
JS: Fix getRawEnclosingStmt call
asgerf Oct 3, 2025
b1418e1
JS: Add overlay[local?] to new summaries after rebasing
asgerf Oct 10, 2025
c09563f
JS: Make more general-purpose data flow things local
asgerf Oct 10, 2025
8892097
JS: Overlay annotations for some failing tests
tausbn Oct 10, 2025
66febb2
JS: Add some overlay[caller] and a pragma[nomagic] annotations
asgerf Oct 15, 2025
e72232f
JS: Add more overlay[caller?] annotations
asgerf Oct 15, 2025
ac3913e
JS: Fix bad join in DuplicateProperty.ql
asgerf Oct 16, 2025
5dd87e3
JS: Add overlay[local] to restore magic in unwrap() predicate
asgerf Oct 16, 2025
269489e
JS: Avoid bad join in shared predicate induced by 'forex'.
asgerf Oct 16, 2025
4645f32
JS: Avoid more bad joins due to locality
asgerf Oct 20, 2025
0594f84
JS: Improve join orders related to getABooleanValue()
asgerf Oct 22, 2025
6498cd1
JS: Remove obsolete overlay[global] annotations
asgerf Oct 31, 2025
46b1387
JS: Make isAssignedInUniqueFile global, as it should be
asgerf Nov 3, 2025
16e7dc1
Sync ApiGraphModelsExtensions.qll
asgerf Nov 3, 2025
ecfa946
Sync ApiGraphModels.qll
asgerf Nov 3, 2025
578355a
JS: Fix bad join in CallGraphs.qll
asgerf Nov 11, 2025
c7341f2
JS: Fix bad join in BarrierGuards.qll
asgerf Nov 11, 2025
a405b7b
JS: Add discard predicates for locations
asgerf Nov 17, 2025
4b57b44
JS: Factor out some code
asgerf Nov 17, 2025
a0965f3
JS: Also discard JSON, YAML, and XML
asgerf Nov 18, 2025
8fef604
JS: Remove out-commented code
asgerf Nov 19, 2025
efa438a
JS: Move identityFunctionStep back into CachedSteps module
asgerf Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions javascript/ql/lib/Expressions/ExprHasNoEffect.qll
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
* Provides classes and predicates for the 'js/useless-expression' query.
*/
overlay[local]
module;

import javascript
import DOMProperties
Expand Down Expand Up @@ -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() |
Expand All @@ -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()) }
}
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions javascript/ql/lib/LanguageFeatures/UnusedIndexVariable.qll
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/**
* Provides a predicate for identifying unused index variables in loops.
*/
overlay[local]
module;

import javascript

Expand Down
20 changes: 16 additions & 4 deletions javascript/ql/lib/semmle/javascript/AMD.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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. */
Expand Down Expand Up @@ -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`
Expand All @@ -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 |
Expand All @@ -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() }

Expand Down Expand Up @@ -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)
Expand All @@ -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
) {
Expand All @@ -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
Expand Down Expand Up @@ -348,21 +361,20 @@ 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
name = pwn.getPropertyName()
)
}

overlay[global]
override DataFlow::Node getABulkExportedNode() {
// Assigned to `module.exports` via the factory's `module` parameter
exists(AbstractModuleObject m, DataFlow::PropWrite write |
Expand Down
8 changes: 8 additions & 0 deletions javascript/ql/lib/semmle/javascript/AST.qll
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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) }

/**
Expand All @@ -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 }

/**
Expand All @@ -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) }
}
}
2 changes: 2 additions & 0 deletions javascript/ql/lib/semmle/javascript/CFG.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 5 additions & 0 deletions javascript/ql/lib/semmle/javascript/Classes.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 }

/**
Expand Down Expand Up @@ -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()
}
Expand Down Expand Up @@ -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() }

/**
Expand Down
Loading
Loading