Skip to content

Commit 94c2e0b

Browse files
author
Max Schaefer
committed
Improve detection of UMD modules.
We previously required the `define` to appear directly as an expression statement, but there are common patterns where this is not the case.
1 parent 05b570a commit 94c2e0b

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

javascript/ql/lib/semmle/javascript/AMD.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import javascript
77
private import semmle.javascript.internal.CachedStages
8+
private import Expressions.ExprHasNoEffect
89

910
/**
1011
* An AMD `define` call.
@@ -26,7 +27,7 @@ private import semmle.javascript.internal.CachedStages
2627
*/
2728
class AmdModuleDefinition extends CallExpr {
2829
AmdModuleDefinition() {
29-
getParent() instanceof ExprStmt and
30+
inVoidContext(this) and
3031
getCallee().(GlobalVarAccess).getName() = "define" and
3132
exists(int n | n = getNumArgument() |
3233
n = 1

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ amoModule_exports
1212
| tst5.js:1:1:6:3 | <toplevel> | foo | tst5.js:3:14:3:18 | a.foo |
1313
| tst.js:1:1:6:3 | <toplevel> | bar | tst.js:4:14:4:18 | b.bar |
1414
| tst.js:1:1:6:3 | <toplevel> | foo | tst.js:3:14:3:18 | a.foo |
15+
| umd2.js:1:1:12:4 | <toplevel> | bar | umd2.js:9:14:9:18 | a.foo |
16+
| umd2.js:1:1:12:4 | <toplevel> | foo | umd2.js:10:14:10:18 | b.bar |
1517
| umd.js:1:1:14:4 | <toplevel> | bar | umd.js:11:14:11:18 | a.foo |
1618
| umd.js:1:1:14:4 | <toplevel> | foo | umd.js:12:14:12:18 | b.bar |
1719
amdModule
@@ -25,6 +27,7 @@ amdModule
2527
| tst4.js:1:1:11:3 | <toplevel> | tst4.js:1:1:11:2 | define( ... };\\n}) |
2628
| tst5.js:1:1:6:3 | <toplevel> | tst5.js:1:1:6:2 | define( ... };\\n}) |
2729
| tst.js:1:1:6:3 | <toplevel> | tst.js:1:1:6:2 | define( ... };\\n}) |
30+
| umd2.js:1:1:12:4 | <toplevel> | umd2.js:5:13:5:47 | define( ... actory) |
2831
| umd.js:1:1:14:4 | <toplevel> | umd.js:4:9:4:43 | define( ... actory) |
2932
getDependencyParameter
3033
| tst2.js:1:1:3:2 | define( ... 42;\\n}) | exports | tst2.js:1:30:1:36 | exports |
@@ -35,6 +38,8 @@ getDependencyParameter
3538
| tst5.js:1:1:6:2 | define( ... };\\n}) | ./dir/b | tst5.js:1:40:1:44 | {bar} |
3639
| tst.js:1:1:6:2 | define( ... };\\n}) | ./a | tst.js:1:37:1:37 | a |
3740
| tst.js:1:1:6:2 | define( ... };\\n}) | ./dir/b | tst.js:1:40:1:40 | b |
41+
| umd2.js:5:13:5:47 | define( ... actory) | ./a | umd2.js:7:19:7:19 | a |
42+
| umd2.js:5:13:5:47 | define( ... actory) | ./dir/b | umd2.js:7:22:7:22 | b |
3843
| umd.js:4:9:4:43 | define( ... actory) | ./a | umd.js:9:19:9:19 | a |
3944
| umd.js:4:9:4:43 | define( ... actory) | ./dir/b | umd.js:9:22:9:22 | b |
4045
amdModuleDefinition
@@ -48,6 +53,8 @@ amdModuleDefinition
4853
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:6:11:11:1 | functio ... };\\n} |
4954
| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:1:28:6:1 | functio ... };\\n} |
5055
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:28:6:1 | functio ... };\\n} |
56+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:1:22:1:28 | factory |
57+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:7:9:12:1 | functio ... };\\n} |
5158
| umd.js:4:9:4:43 | define( ... actory) | umd.js:1:18:1:24 | factory |
5259
| umd.js:4:9:4:43 | define( ... actory) | umd.js:9:9:14:1 | functio ... };\\n} |
5360
amdModuleDependencies
@@ -61,6 +68,8 @@ amdModuleDependencies
6168
| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:1:16:1:24 | './dir/b' |
6269
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:9:1:13 | './a' |
6370
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:1:16:1:24 | './dir/b' |
71+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:5:21:5:25 | './a' |
72+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:5:28:5:36 | './dir/b' |
6473
| umd.js:4:9:4:43 | define( ... actory) | umd.js:4:17:4:21 | './a' |
6574
| umd.js:4:9:4:43 | define( ... actory) | umd.js:4:24:4:32 | './dir/b' |
6675
amdModuleExportedSymbol
@@ -77,6 +86,8 @@ amdModuleExportedSymbol
7786
| tst5.js:1:1:6:3 | <toplevel> | foo |
7887
| tst.js:1:1:6:3 | <toplevel> | bar |
7988
| tst.js:1:1:6:3 | <toplevel> | foo |
89+
| umd2.js:1:1:12:4 | <toplevel> | bar |
90+
| umd2.js:1:1:12:4 | <toplevel> | foo |
8091
| umd.js:1:1:14:4 | <toplevel> | bar |
8192
| umd.js:1:1:14:4 | <toplevel> | foo |
8293
amdModuleExpr
@@ -88,6 +99,12 @@ amdModuleExpr
8899
| tst4.js:1:1:11:2 | define( ... };\\n}) | tst4.js:7:12:10:5 | {\\n ... r\\n } | tst4.js:7:12:10:5 | {\\n ... r\\n } |
89100
| tst5.js:1:1:6:2 | define( ... };\\n}) | tst5.js:2:12:5:5 | {\\n ... r\\n } | tst5.js:2:12:5:5 | {\\n ... r\\n } |
90101
| tst.js:1:1:6:2 | define( ... };\\n}) | tst.js:2:12:5:5 | {\\n ... r\\n } | tst.js:2:12:5:5 | {\\n ... r\\n } |
102+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:1:22:1:28 | factory | umd2.js:1:22:1:28 | factory |
103+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:1:22:1:28 | factory | umd2.js:7:9:12:1 | functio ... };\\n} |
104+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:1:22:1:28 | factory | umd2.js:8:12:11:5 | {\\n ... r\\n } |
105+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:8:12:11:5 | {\\n ... r\\n } | umd2.js:1:22:1:28 | factory |
106+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:8:12:11:5 | {\\n ... r\\n } | umd2.js:7:9:12:1 | functio ... };\\n} |
107+
| umd2.js:5:13:5:47 | define( ... actory) | umd2.js:8:12:11:5 | {\\n ... r\\n } | umd2.js:8:12:11:5 | {\\n ... r\\n } |
91108
| umd.js:4:9:4:43 | define( ... actory) | umd.js:1:18:1:24 | factory | umd.js:1:18:1:24 | factory |
92109
| umd.js:4:9:4:43 | define( ... actory) | umd.js:1:18:1:24 | factory | umd.js:9:9:14:1 | functio ... };\\n} |
93110
| umd.js:4:9:4:43 | define( ... actory) | umd.js:1:18:1:24 | factory | umd.js:10:12:13:5 | {\\n ... r\\n } |
@@ -103,5 +120,9 @@ amdModuleImportedModule
103120
| tst5.js:1:1:6:3 | <toplevel> | tst5.js:1:16:1:24 | './dir/b' | dir/b.js:1:1:3:3 | <toplevel> |
104121
| tst.js:1:1:6:3 | <toplevel> | tst.js:1:9:1:13 | './a' | a.js:1:1:3:3 | <toplevel> |
105122
| tst.js:1:1:6:3 | <toplevel> | tst.js:1:16:1:24 | './dir/b' | dir/b.js:1:1:3:3 | <toplevel> |
123+
| umd2.js:1:1:12:4 | <toplevel> | umd2.js:3:34:3:47 | require('./a') | a.js:1:1:3:3 | <toplevel> |
124+
| umd2.js:1:1:12:4 | <toplevel> | umd2.js:3:50:3:67 | require('./dir/b') | dir/b.js:1:1:3:3 | <toplevel> |
125+
| umd2.js:1:1:12:4 | <toplevel> | umd2.js:5:21:5:25 | './a' | a.js:1:1:3:3 | <toplevel> |
126+
| umd2.js:1:1:12:4 | <toplevel> | umd2.js:5:28:5:36 | './dir/b' | dir/b.js:1:1:3:3 | <toplevel> |
106127
| umd.js:1:1:14:4 | <toplevel> | umd.js:4:17:4:21 | './a' | a.js:1:1:3:3 | <toplevel> |
107128
| umd.js:1:1:14:4 | <toplevel> | umd.js:4:24:4:32 | './dir/b' | dir/b.js:1:1:3:3 | <toplevel> |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
; (function (global, factory) {
2+
typeof exports === 'object' && typeof module !== 'undefined' ?
3+
module.exports = factory(require('./a'), require('./dir/b')) :
4+
typeof define === 'function' && define.amd ?
5+
define(['./a', './dir/b'], factory) :
6+
global.mymodule = factory(global.a, global.dir.b)
7+
}(this, function (a, b) {
8+
return {
9+
bar: a.foo,
10+
foo: b.bar
11+
};
12+
}));

0 commit comments

Comments
 (0)