Skip to content

Commit

Permalink
Merge pull request #14007 from asgerf/js/import-path-string
Browse files Browse the repository at this point in the history
JS: Follow immediate predecessors in path resolution
  • Loading branch information
asgerf authored Aug 23, 2023
2 parents 54c2221 + ae2a1c7 commit 2b540e2
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 1 deletion.
24 changes: 23 additions & 1 deletion javascript/ql/lib/semmle/javascript/Paths.qll
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,25 @@ private class PathExprString extends PathString {
}
}

pragma[nomagic]
private DataFlow::Node getAPathExprAlias(PathExpr expr) {
result.getImmediatePredecessor().asExpr() = expr
or
result.getImmediatePredecessor() = getAPathExprAlias(expr)
}

private class PathExprFromAlias extends PathExpr {
private PathExpr other;

PathExprFromAlias() { this = getAPathExprAlias(other).asExpr() }

override string getValue() { result = other.getValue() }

override Folder getAdditionalSearchRoot(int priority) {
result = other.getAdditionalSearchRoot(priority)
}
}

/**
* A path expression of the form `p + q`, where both `p` and `q`
* are path expressions.
Expand Down Expand Up @@ -413,6 +432,9 @@ private class ConcatPath extends PathExpr {
* Examples include arguments to the CommonJS `require` function or AMD dependency arguments.
*/
abstract class PathExprCandidate extends Expr {
pragma[nomagic]
private Expr getAPart1() { result = this or result = this.getAPart().getAChildExpr() }

/**
* Gets an expression that is nested inside this expression.
*
Expand All @@ -421,5 +443,5 @@ abstract class PathExprCandidate extends Expr {
* `ConstantString`s).
*/
pragma[nomagic]
Expr getAPart() { result = this or result = this.getAPart().getAChildExpr() }
Expr getAPart() { result = this.getAPart1().flow().getImmediatePredecessor*().asExpr() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Imports can now be resolved in more cases, where a non-constant string expression is passed to a `require()` call.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
require(__dirname + '/a');

var x = __dirname;
var y = '/a';
require(x + y);
3 changes: 3 additions & 0 deletions javascript/ql/test/library-tests/Modules/tests.expected
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ test_NamedImportSpecifier
| reExportNamespaceClient.js:1:10:1:11 | ns |
test_OtherImports
| es2015_require.js:1:11:1:24 | require('./d') | d.js:1:1:5:0 | <toplevel> |
| import-indirect-path.js:1:1:1:25 | require ... + '/a') | a.js:1:1:5:32 | <toplevel> |
| import-indirect-path.js:5:1:5:14 | require(x + y) | a.js:1:1:5:32 | <toplevel> |
test_ReExportDeclarations
| b.js:7:1:7:21 | export ... './a'; | b.js:7:16:7:20 | './a' |
| d.js:4:1:4:20 | export * from 'm/c'; | d.js:4:15:4:19 | 'm/c' |
Expand All @@ -103,6 +105,7 @@ test_getAnImportedModule
| library-tests/Modules/es2015_require.js | library-tests/Modules/d.js |
| library-tests/Modules/f.ts | library-tests/Modules/e.js |
| library-tests/Modules/g.ts | library-tests/Modules/f.ts |
| library-tests/Modules/import-indirect-path.js | library-tests/Modules/a.js |
| library-tests/Modules/import-ts-with-js-extension.ts | library-tests/Modules/f.ts |
| library-tests/Modules/m/c.js | library-tests/Modules/b.js |
| library-tests/Modules/reExportNamespaceClient.js | library-tests/Modules/reExportNamespace.js |
Expand Down

0 comments on commit 2b540e2

Please sign in to comment.