Skip to content

Commit d9b3e46

Browse files
author
Max Schaefer
authored
Merge pull request #1351 from asger-semmle/js-incomplete-nodes
JS: Mark some more nodes as incomplete
2 parents bad5465 + 180b544 commit d9b3e46

File tree

4 files changed

+87
-20
lines changed

4 files changed

+87
-20
lines changed

javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1270,6 +1270,16 @@ module DataFlow {
12701270
(e instanceof AwaitExpr or e instanceof DynamicImportExpr) and
12711271
cause = "await"
12721272
)
1273+
or
1274+
nd instanceof TExceptionalInvocationReturnNode and cause = "call"
1275+
or
1276+
nd instanceof TExceptionalFunctionReturnNode and cause = "call"
1277+
or
1278+
exists(PropertyPattern p | nd = TPropNode(p)) and cause = "heap"
1279+
or
1280+
nd instanceof TElementPatternNode and cause = "heap"
1281+
or
1282+
nd instanceof UnusedParameterNode and cause = "call"
12731283
}
12741284

12751285
/**
@@ -1288,9 +1298,6 @@ module DataFlow {
12881298
or
12891299
exists(ComprehensionBlock cb | def = cb.getIterator()) and
12901300
cause = "yield"
1291-
or
1292-
def.getTarget() instanceof DestructuringPattern and
1293-
cause = "heap"
12941301
}
12951302
import Nodes
12961303
import Sources
Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,96 @@
1+
| eval.js:1:1:5:1 | exceptional return of function k | call |
12
| eval.js:2:7:2:12 | x | eval |
23
| eval.js:3:3:3:6 | eval | global |
34
| eval.js:3:3:3:16 | eval("x = 23") | call |
5+
| eval.js:3:3:3:16 | exceptional return of eval("x = 23") | call |
6+
| sources.js:1:1:1:12 | exceptional return of new (x => x) | call |
47
| sources.js:1:6:1:6 | x | call |
8+
| sources.js:1:6:1:11 | exceptional return of anonymous function | call |
9+
| sources.js:3:1:5:6 | exceptional return of (functi ... \\n})(23) | call |
10+
| sources.js:3:2:5:1 | exceptional return of anonymous function | call |
511
| tst.js:1:10:1:11 | fs | import |
12+
| tst.js:16:1:20:9 | exceptional return of (functi ... ("arg") | call |
13+
| tst.js:16:2:20:1 | exceptional return of function f | call |
614
| tst.js:17:7:17:10 | Math | global |
715
| tst.js:17:7:17:17 | Math.random | global |
816
| tst.js:17:7:17:17 | Math.random | heap |
917
| tst.js:17:7:17:19 | Math.random() | call |
10-
| tst.js:22:5:22:25 | readFileSync | heap |
18+
| tst.js:17:7:17:19 | exceptional return of Math.random() | call |
19+
| tst.js:22:7:22:18 | readFileSync | heap |
20+
| tst.js:28:1:30:3 | exceptional return of (() =>\\n ... les\\n)() | call |
21+
| tst.js:28:2:29:3 | exceptional return of anonymous function | call |
22+
| tst.js:32:1:34:1 | exceptional return of function g | call |
23+
| tst.js:32:12:32:12 | b | call |
24+
| tst.js:35:1:35:7 | exceptional return of g(true) | call |
1125
| tst.js:35:1:35:7 | g(true) | call |
26+
| tst.js:39:4:41:3 | exceptional return of method m | call |
1227
| tst.js:40:5:40:8 | this | call |
1328
| tst.js:43:1:43:3 | o.x | heap |
1429
| tst.js:44:1:44:3 | o.m | heap |
30+
| tst.js:44:1:44:5 | exceptional return of o.m() | call |
1531
| tst.js:44:1:44:5 | o.m() | call |
1632
| tst.js:47:1:47:6 | global | global |
1733
| tst.js:49:17:49:17 | B | global |
34+
| tst.js:50:14:53:3 | exceptional return of constructor of class A | call |
1835
| tst.js:51:5:51:9 | super | call |
36+
| tst.js:51:5:51:13 | exceptional return of super(42) | call |
1937
| tst.js:51:5:51:13 | super(42) | call |
2038
| tst.js:52:5:52:14 | new.target | call |
2139
| tst.js:58:1:58:3 | tag | global |
2240
| tst.js:58:1:58:13 | tag `x: ${x}` | call |
2341
| tst.js:61:1:61:5 | ::o.m | call |
2442
| tst.js:61:3:61:5 | o.m | heap |
2543
| tst.js:62:1:62:4 | o::g | call |
44+
| tst.js:64:1:67:1 | exceptional return of function h | call |
2645
| tst.js:65:3:65:10 | yield 42 | yield |
2746
| tst.js:66:13:66:25 | function.sent | yield |
47+
| tst.js:68:12:68:14 | exceptional return of h() | call |
2848
| tst.js:68:12:68:14 | h() | call |
2949
| tst.js:69:1:69:9 | iter.next | heap |
50+
| tst.js:69:1:69:13 | exceptional return of iter.next(23) | call |
3051
| tst.js:69:1:69:13 | iter.next(23) | call |
52+
| tst.js:71:1:73:1 | exceptional return of function k | call |
3153
| tst.js:72:3:72:11 | await p() | await |
3254
| tst.js:72:9:72:9 | p | global |
55+
| tst.js:72:9:72:11 | exceptional return of p() | call |
3356
| tst.js:72:9:72:11 | p() | call |
3457
| tst.js:75:9:75:21 | import('foo') | await |
3558
| tst.js:77:10:77:10 | i | heap |
3659
| tst.js:80:10:80:10 | v | heap |
3760
| tst.js:83:18:83:18 | v | yield |
3861
| tst.js:85:18:85:18 | v | yield |
39-
| tst.js:87:11:87:24 | o | heap |
40-
| tst.js:87:11:87:24 | x | heap |
41-
| tst.js:88:7:88:18 | y | heap |
42-
| tst.js:90:4:90:15 | z | heap |
43-
| tst.js:98:11:98:24 | rest | heap |
44-
| tst.js:98:11:98:24 | x | heap |
45-
| tst.js:99:7:99:18 | y | heap |
46-
| tst.js:101:3:101:16 | z | heap |
47-
| tst.js:108:6:108:38 | v1a | heap |
48-
| tst.js:108:6:108:38 | v1b | heap |
49-
| tst.js:108:6:108:38 | v1c | heap |
62+
| tst.js:87:1:96:2 | exceptional return of (functi ... r: 0\\n}) | call |
63+
| tst.js:87:2:92:1 | exceptional return of anonymous function | call |
64+
| tst.js:87:13:87:16 | p: x | heap |
65+
| tst.js:88:9:88:12 | q: y | heap |
66+
| tst.js:90:6:90:9 | r: z | heap |
67+
| tst.js:98:1:103:17 | exceptional return of (functi ... 3, 0 ]) | call |
68+
| tst.js:98:2:103:1 | exceptional return of anonymous function | call |
69+
| tst.js:98:13:98:13 | x | heap |
70+
| tst.js:99:9:99:9 | y | heap |
71+
| tst.js:101:7:101:7 | z | heap |
72+
| tst.js:107:2:113:1 | exceptional return of anonymous function | call |
73+
| tst.js:108:7:108:9 | v1a | heap |
74+
| tst.js:108:12:108:20 | v1b = o1b | heap |
5075
| tst.js:108:18:108:20 | o1b | global |
76+
| tst.js:108:23:108:31 | v1c = o1c | heap |
5177
| tst.js:108:29:108:31 | o1c | global |
5278
| tst.js:108:36:108:38 | o1d | global |
53-
| tst.js:111:6:111:38 | v2a | heap |
54-
| tst.js:111:6:111:38 | v2b | heap |
55-
| tst.js:111:6:111:38 | v2c | heap |
79+
| tst.js:111:7:111:9 | v2a | heap |
80+
| tst.js:111:12:111:14 | v2b | heap |
5681
| tst.js:111:18:111:20 | o2b | global |
82+
| tst.js:111:23:111:25 | v2c | heap |
5783
| tst.js:111:29:111:31 | o2c | global |
5884
| tst.js:111:36:111:38 | o2d | global |
5985
| tst.ts:2:14:2:19 | x | namespace |
86+
| tst.ts:3:3:3:8 | exceptional return of setX() | call |
6087
| tst.ts:3:3:3:8 | setX() | call |
88+
| tst.ts:7:1:9:1 | exceptional return of function setX | call |
6189
| tst.ts:8:3:8:5 | A.x | heap |
6290
| tst.ts:11:11:11:13 | A.x | heap |
6391
| tst.ts:13:26:13:29 | List | global |
6492
| tst.ts:13:39:13:38 | args | call |
93+
| tst.ts:13:39:13:38 | exceptional return of default constructor of class StringList | call |
94+
| tst.ts:13:39:13:38 | exceptional return of super(...args) | call |
6595
| tst.ts:13:39:13:38 | super | call |
6696
| tst.ts:13:39:13:38 | super(...args) | call |

javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
typeInferenceMismatch
2+
| addexpr.js:4:10:4:17 | source() | addexpr.js:4:5:4:17 | x |
3+
| addexpr.js:4:10:4:17 | source() | addexpr.js:6:3:6:14 | x |
4+
| addexpr.js:11:15:11:22 | source() | addexpr.js:17:5:17:18 | value |
5+
| addexpr.js:11:15:11:22 | source() | addexpr.js:19:3:19:14 | value |
6+
#select
17
| access-path-sanitizer.js:2:18:2:25 | source() | access-path-sanitizer.js:4:8:4:12 | obj.x |
28
| addexpr.js:4:10:4:17 | source() | addexpr.js:7:8:7:8 | x |
39
| addexpr.js:11:15:11:22 | source() | addexpr.js:21:8:21:12 | value |

javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,33 @@
11
import javascript
2+
import semmle.javascript.dataflow.InferredTypes
23

34
DataFlow::CallNode getACall(string name) { result.getCalleeName() = name }
45

6+
class Sink extends DataFlow::Node {
7+
Sink() { this = getACall("sink").getAnArgument() }
8+
}
9+
10+
/**
11+
* A node that shouldn't be taintable according to the type inference,
12+
* as it claims to be neither an object nor a string.
13+
*/
14+
class UntaintableNode extends DataFlow::Node {
15+
UntaintableNode() {
16+
not analyze().getAType() = TTObject() and
17+
not analyze().getAType() = TTString()
18+
}
19+
}
20+
521
class BasicConfig extends TaintTracking::Configuration {
622
BasicConfig() { this = "BasicConfig" }
723

824
override predicate isSource(DataFlow::Node node) { node = getACall("source") }
925

10-
override predicate isSink(DataFlow::Node node) { node = getACall("sink").getAnArgument() }
26+
override predicate isSink(DataFlow::Node node) {
27+
node instanceof Sink
28+
or
29+
node instanceof UntaintableNode
30+
}
1131

1232
override predicate isSanitizerGuard(TaintTracking::SanitizerGuardNode node) {
1333
node instanceof BasicSanitizerGuard
@@ -22,6 +42,10 @@ class BasicSanitizerGuard extends TaintTracking::SanitizerGuardNode, DataFlow::C
2242
}
2343
}
2444

25-
from BasicConfig cfg, DataFlow::Node src, DataFlow::Node sink
45+
query predicate typeInferenceMismatch(DataFlow::Node source, UntaintableNode sink) {
46+
any(BasicConfig cfg).hasFlow(source, sink)
47+
}
48+
49+
from BasicConfig cfg, DataFlow::Node src, Sink sink
2650
where cfg.hasFlow(src, sink)
2751
select src, sink

0 commit comments

Comments
 (0)