Skip to content

Commit 444a09a

Browse files
author
Esben Sparre Andreasen
committed
JS: add models of five file system libraries
1 parent 5781b51 commit 444a09a

File tree

5 files changed

+148
-0
lines changed

5 files changed

+148
-0
lines changed

javascript/ql/src/javascript.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import semmle.javascript.frameworks.Credentials
5959
import semmle.javascript.frameworks.CryptoLibraries
6060
import semmle.javascript.frameworks.DigitalOcean
6161
import semmle.javascript.frameworks.Electron
62+
import semmle.javascript.frameworks.Files
6263
import semmle.javascript.frameworks.jQuery
6364
import semmle.javascript.frameworks.LodashUnderscore
6465
import semmle.javascript.frameworks.Logging
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/**
2+
* Provides classes for working with file system libraries.
3+
*/
4+
5+
import javascript
6+
7+
/**
8+
* A file name from the `walk-sync` library.
9+
*/
10+
private class WalkSyncFileNameSource extends FileNameSource {
11+
12+
WalkSyncFileNameSource() {
13+
// `require('walkSync')()`
14+
this = DataFlow::moduleImport("walkSync").getACall()
15+
}
16+
17+
}
18+
19+
/**
20+
* A file name or an array of file names from the `walk` library.
21+
*/
22+
private class WalkFileNameSource extends FileNameSource {
23+
24+
WalkFileNameSource() {
25+
// `stats.name` in `require('walk').walk(_).on(_, (_, stats) => stats.name)`
26+
exists (DataFlow::FunctionNode callback |
27+
callback = DataFlow::moduleMember("walk", "walk").getACall().getAMethodCall("on").getCallback(1) |
28+
this = callback.getParameter(1).getAPropertyRead("name")
29+
)
30+
}
31+
32+
}
33+
34+
/**
35+
* A file name or an array of file names from the `glob` library.
36+
*/
37+
private class GlobFileNameSource extends FileNameSource {
38+
39+
GlobFileNameSource() {
40+
exists (string moduleName |
41+
moduleName = "glob" |
42+
// `require('glob').sync(_)`
43+
this = DataFlow::moduleMember(moduleName, "sync").getACall()
44+
or
45+
// `name` in `require('glob')(_, (e, name) => ...)`
46+
this = DataFlow::moduleImport(moduleName).getACall().getCallback([1..2]).getParameter(1)
47+
or
48+
exists (DataFlow::NewNode instance |
49+
instance = DataFlow::moduleMember(moduleName, "Glob").getAnInstantiation() |
50+
// `name` in `new require('glob').Glob(_, (e, name) => ...)`
51+
this = instance.getCallback([1..2]).getParameter(1) or
52+
// `new require('glob').Glob(_).found`
53+
this = instance.getAPropertyRead("found")
54+
)
55+
)
56+
}
57+
58+
}
59+
60+
/**
61+
* A file name or an array of file names from the `globby` library.
62+
*/
63+
private class GlobbyFileNameSource extends FileNameSource {
64+
65+
GlobbyFileNameSource() {
66+
exists (string moduleName |
67+
moduleName = "globby" |
68+
// `require('globby').sync(_)`
69+
this = DataFlow::moduleMember(moduleName, "sync").getACall()
70+
or
71+
// `files` in `require('globby')(_).then(files => ...)`
72+
this = DataFlow::moduleImport(moduleName).getACall().getAMethodCall("then").getCallback(0).getParameter(0)
73+
)
74+
}
75+
76+
}
77+
78+
/**
79+
* A file name or an array of file names from the `fast-glob` library.
80+
*/
81+
private class FastGlobFileNameSource extends FileNameSource {
82+
83+
FastGlobFileNameSource() {
84+
exists (string moduleName |
85+
moduleName = "fast-glob" |
86+
// `require('fast-glob').sync(_)`
87+
this = DataFlow::moduleMember(moduleName, "sync").getACall()
88+
or
89+
exists (DataFlow::SourceNode f |
90+
f = DataFlow::moduleImport(moduleName)
91+
or
92+
f = DataFlow::moduleMember(moduleName, "async") |
93+
// `files` in `require('fast-glob')(_).then(files => ...)` and
94+
// `files` in `require('fast-glob').async(_).then(files => ...)`
95+
this = f.getACall().getAMethodCall("then").getCallback(0).getParameter(0)
96+
)
97+
or
98+
// `file` in `require('fast-glob').stream(_).on(_, file => ...)`
99+
this = DataFlow::moduleMember(moduleName, "stream").getACall().getAMethodCall("on").getCallback(1).getParameter(0)
100+
)
101+
}
102+
103+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
| tst-file-names.js:7:1:7:10 | walkSync() |
2+
| tst-file-names.js:9:35:9:44 | stats.name |
3+
| tst-file-names.js:11:1:11:12 | glob.sync(_) |
4+
| tst-file-names.js:13:13:13:16 | name |
5+
| tst-file-names.js:15:22:15:25 | name |
6+
| tst-file-names.js:17:1:17:22 | new glo ... ).found |
7+
| tst-file-names.js:19:1:19:14 | globby.sync(_) |
8+
| tst-file-names.js:21:16:21:20 | files |
9+
| tst-file-names.js:23:1:23:16 | fastGlob.sync(_) |
10+
| tst-file-names.js:25:18:25:22 | files |
11+
| tst-file-names.js:27:24:27:28 | files |
12+
| tst-file-names.js:29:27:29:30 | file |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import javascript
2+
3+
select any(FileNameSource s)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
let walkSync = require('walkSync'),
2+
walk = require('walk'),
3+
glob = require('glob'),
4+
globby = require('globby'),
5+
fastGlob = require('fast-glob');
6+
7+
walkSync();
8+
9+
walk.walk(_).on(_, (_, stats) => stats.name); // XXX
10+
11+
glob.sync(_);
12+
13+
glob(_, (e, name) => name);
14+
15+
new glob.Glob(_, (e, name) => name);
16+
17+
new glob.Glob(_).found;
18+
19+
globby.sync(_);
20+
21+
globby(_).then(files => files)
22+
23+
fastGlob.sync(_);
24+
25+
fastGlob(_).then(files => files);
26+
27+
fastGlob.async(_).then(files => files);
28+
29+
fastGlob.stream(_).on(_, file => file); // XXX

0 commit comments

Comments
 (0)