Skip to content

Commit 2b540e2

Browse files
authored
Merge pull request github#14007 from asgerf/js/import-path-string
JS: Follow immediate predecessors in path resolution
2 parents 54c2221 + ae2a1c7 commit 2b540e2

File tree

4 files changed

+35
-1
lines changed

4 files changed

+35
-1
lines changed

javascript/ql/lib/semmle/javascript/Paths.qll

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,25 @@ private class PathExprString extends PathString {
380380
}
381381
}
382382

383+
pragma[nomagic]
384+
private DataFlow::Node getAPathExprAlias(PathExpr expr) {
385+
result.getImmediatePredecessor().asExpr() = expr
386+
or
387+
result.getImmediatePredecessor() = getAPathExprAlias(expr)
388+
}
389+
390+
private class PathExprFromAlias extends PathExpr {
391+
private PathExpr other;
392+
393+
PathExprFromAlias() { this = getAPathExprAlias(other).asExpr() }
394+
395+
override string getValue() { result = other.getValue() }
396+
397+
override Folder getAdditionalSearchRoot(int priority) {
398+
result = other.getAdditionalSearchRoot(priority)
399+
}
400+
}
401+
383402
/**
384403
* A path expression of the form `p + q`, where both `p` and `q`
385404
* are path expressions.
@@ -413,6 +432,9 @@ private class ConcatPath extends PathExpr {
413432
* Examples include arguments to the CommonJS `require` function or AMD dependency arguments.
414433
*/
415434
abstract class PathExprCandidate extends Expr {
435+
pragma[nomagic]
436+
private Expr getAPart1() { result = this or result = this.getAPart().getAChildExpr() }
437+
416438
/**
417439
* Gets an expression that is nested inside this expression.
418440
*
@@ -421,5 +443,5 @@ abstract class PathExprCandidate extends Expr {
421443
* `ConstantString`s).
422444
*/
423445
pragma[nomagic]
424-
Expr getAPart() { result = this or result = this.getAPart().getAChildExpr() }
446+
Expr getAPart() { result = this.getAPart1().flow().getImmediatePredecessor*().asExpr() }
425447
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Imports can now be resolved in more cases, where a non-constant string expression is passed to a `require()` call.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
require(__dirname + '/a');
2+
3+
var x = __dirname;
4+
var y = '/a';
5+
require(x + y);

javascript/ql/test/library-tests/Modules/tests.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ test_NamedImportSpecifier
9090
| reExportNamespaceClient.js:1:10:1:11 | ns |
9191
test_OtherImports
9292
| es2015_require.js:1:11:1:24 | require('./d') | d.js:1:1:5:0 | <toplevel> |
93+
| import-indirect-path.js:1:1:1:25 | require ... + '/a') | a.js:1:1:5:32 | <toplevel> |
94+
| import-indirect-path.js:5:1:5:14 | require(x + y) | a.js:1:1:5:32 | <toplevel> |
9395
test_ReExportDeclarations
9496
| b.js:7:1:7:21 | export ... './a'; | b.js:7:16:7:20 | './a' |
9597
| d.js:4:1:4:20 | export * from 'm/c'; | d.js:4:15:4:19 | 'm/c' |
@@ -103,6 +105,7 @@ test_getAnImportedModule
103105
| library-tests/Modules/es2015_require.js | library-tests/Modules/d.js |
104106
| library-tests/Modules/f.ts | library-tests/Modules/e.js |
105107
| library-tests/Modules/g.ts | library-tests/Modules/f.ts |
108+
| library-tests/Modules/import-indirect-path.js | library-tests/Modules/a.js |
106109
| library-tests/Modules/import-ts-with-js-extension.ts | library-tests/Modules/f.ts |
107110
| library-tests/Modules/m/c.js | library-tests/Modules/b.js |
108111
| library-tests/Modules/reExportNamespaceClient.js | library-tests/Modules/reExportNamespace.js |

0 commit comments

Comments
 (0)