Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3422fa3

Browse files
committed
JS: Add test
1 parent e6a1374 commit 3422fa3

6 files changed

Lines changed: 212 additions & 4 deletions

File tree

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,11 @@ module StepSummary {
103103
// Flow out of function
104104
returnStep(predNode, succ) and
105105
summary = return()
106+
or
107+
// Flow through an instance field between members of the same class
108+
DataFlow::localFieldStep(predNode, succ) and
109+
summary = level()
106110
)
107-
or
108-
DataFlow::localFieldStep(pred, succ) and
109-
summary = level()
110111
}
111112

112113
/**
@@ -207,7 +208,7 @@ private newtype TTypeBackTracker = MkTypeBackTracker(boolean hasReturn) {
207208
* ```
208209
* DataFlow::SourceNode myCallback(DataFlow::TypeBackTracker t) {
209210
* t.start() and
210-
* result = (< some API call >).getParameter(< n >).getALocalSource()
211+
* result = (< some API call >).getArgument(< n >).getALocalSource()
211212
* or
212213
* exists (DataFlow::TypeTracker t2 |
213214
* result = myCallback(t2).backtrack(t2, t)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
test_ApiObject
2+
| tst.js:3:11:3:21 | new myapi() |
3+
| tst.js:15:10:15:21 | api.chain1() |
4+
| tst.js:15:10:15:30 | api.cha ... hain2() |
5+
test_Connection
6+
| tst.js:6:15:6:18 | conn |
7+
| tst.js:10:5:10:19 | this.connection |
8+
| tst.js:15:10:15:49 | api.cha ... ction() |
9+
| tst.js:18:7:18:21 | getConnection() |
10+
test_DataCallback
11+
| tst.js:9:11:9:12 | cb |
12+
| tst.js:20:1:22:1 | functio ... ata);\\n} |
13+
test_DataValue
14+
| tst.js:20:18:20:21 | data |
15+
| tst.js:24:19:24:22 | data |
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import javascript
2+
3+
string chainableMethod() {
4+
result = "chain1" or
5+
result = "chain2"
6+
}
7+
8+
class ApiObject extends DataFlow::NewNode {
9+
ApiObject() {
10+
this = DataFlow::moduleImport("@test/myapi").getAnInstantiation()
11+
}
12+
13+
DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
14+
t.start() and
15+
result = this
16+
or
17+
t.start() and
18+
result = ref(_).getAMethodCall(chainableMethod())
19+
or
20+
exists(DataFlow::TypeTracker t2 |
21+
result = ref(t2).track(t2, t)
22+
)
23+
}
24+
25+
DataFlow::SourceNode ref() {
26+
result = ref(_)
27+
}
28+
}
29+
30+
class Connection extends DataFlow::SourceNode {
31+
ApiObject api;
32+
33+
Connection() {
34+
this = api.ref().getAMethodCall("createConnection")
35+
}
36+
37+
DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
38+
t.start() and
39+
result = this
40+
or
41+
exists(DataFlow::TypeTracker t2 |
42+
result = ref(t2).track(t2, t)
43+
)
44+
}
45+
46+
DataFlow::SourceNode ref() {
47+
result = ref(_)
48+
}
49+
50+
DataFlow::SourceNode getACallbackNode(DataFlow::TypeBackTracker t) {
51+
t.start() and
52+
result = ref().getAMethodCall("getData").getArgument(0).getALocalSource()
53+
or
54+
exists(DataFlow::TypeBackTracker t2 |
55+
result = getACallbackNode(t2).backtrack(t2, t)
56+
)
57+
}
58+
59+
DataFlow::FunctionNode getACallback() {
60+
result = getACallbackNode(_).getAFunctionValue()
61+
}
62+
}
63+
64+
class DataValue extends DataFlow::SourceNode {
65+
Connection connection;
66+
67+
DataValue() {
68+
this = connection.getACallback().getParameter(0)
69+
}
70+
71+
DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
72+
t.start() and
73+
result = this
74+
or
75+
exists(DataFlow::TypeTracker t2 |
76+
result = ref(t2).track(t2, t)
77+
)
78+
}
79+
80+
DataFlow::SourceNode ref() {
81+
result = ref(_)
82+
}
83+
}
84+
85+
query DataFlow::SourceNode test_ApiObject() { result = any(ApiObject obj).ref() }
86+
87+
query DataFlow::SourceNode test_Connection() { result = any(Connection c).ref() }
88+
89+
query DataFlow::SourceNode test_DataCallback() { result = any(Connection c).getACallbackNode(_) }
90+
91+
query DataFlow::SourceNode test_DataValue() { result = any(DataValue v).ref() }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiObject
2+
| tst.js:3:11:3:21 | new myapi() |
3+
| tst.js:15:10:15:21 | api.chain1() |
4+
| tst.js:15:10:15:30 | api.cha ... hain2() |
5+
connection
6+
| type tracker with call steps | tst.js:6:15:6:18 | conn |
7+
| type tracker with call steps | tst.js:10:5:10:19 | this.connection |
8+
| type tracker without call steps | tst.js:15:10:15:49 | api.cha ... ction() |
9+
| type tracker without call steps | tst.js:18:7:18:21 | getConnection() |
10+
dataCallback
11+
| tst.js:9:11:9:12 | cb |
12+
| tst.js:20:1:22:1 | functio ... ata);\\n} |
13+
dataValue
14+
| tst.js:20:18:20:21 | data |
15+
| tst.js:24:19:24:22 | data |
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import javascript
2+
3+
string chainableMethod() {
4+
result = "chain1" or
5+
result = "chain2"
6+
}
7+
8+
DataFlow::SourceNode apiObject(DataFlow::TypeTracker t) {
9+
t.start() and
10+
result = DataFlow::moduleImport("@test/myapi").getAnInstantiation()
11+
or
12+
t.start() and
13+
result = apiObject(_).getAMethodCall(chainableMethod())
14+
or
15+
exists(DataFlow::TypeTracker t2 |
16+
result = apiObject(t2).track(t2, t)
17+
)
18+
}
19+
20+
query DataFlow::SourceNode apiObject() {
21+
result = apiObject(_)
22+
}
23+
24+
query DataFlow::SourceNode connection(DataFlow::TypeTracker t) {
25+
t.start() and
26+
result = apiObject().getAMethodCall("createConnection")
27+
or
28+
exists(DataFlow::TypeTracker t2 |
29+
result = connection(t2).track(t2, t)
30+
)
31+
}
32+
33+
DataFlow::SourceNode connection() {
34+
result = connection(_)
35+
}
36+
37+
DataFlow::SourceNode dataCallback(DataFlow::TypeBackTracker t) {
38+
t.start() and
39+
result = connection().getAMethodCall("getData").getArgument(0).getALocalSource()
40+
or
41+
exists(DataFlow::TypeBackTracker t2 |
42+
result = dataCallback(t2).backtrack(t2, t)
43+
)
44+
}
45+
46+
query DataFlow::SourceNode dataCallback() {
47+
result = dataCallback(_)
48+
}
49+
50+
DataFlow::SourceNode dataValue(DataFlow::TypeTracker t) {
51+
t.start() and
52+
result = dataCallback().getAFunctionValue().getParameter(0)
53+
or
54+
exists(DataFlow::TypeTracker t2 |
55+
result = dataValue(t2).track(t2, t)
56+
)
57+
}
58+
59+
query DataFlow::SourceNode dataValue() {
60+
result = dataValue(_)
61+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import myapi from "@test/myapi";
2+
3+
let api = new myapi();
4+
5+
class C {
6+
constructor(conn) {
7+
this.connection = conn;
8+
}
9+
getData(cb) {
10+
this.connection.getData(cb);
11+
}
12+
}
13+
14+
function getConnection() {
15+
return api.chain1().chain2().createConnection();
16+
}
17+
18+
new C(getConnection()).getData(useData);
19+
20+
function useData(data) {
21+
useData2(data);
22+
}
23+
24+
function useData2(data) {
25+
}

0 commit comments

Comments
 (0)