mirror of
https://github.com/github/codeql.git
synced 2026-05-01 11:45:14 +02:00
JS: Add test
This commit is contained in:
@@ -103,10 +103,11 @@ module StepSummary {
|
||||
// Flow out of function
|
||||
returnStep(predNode, succ) and
|
||||
summary = return()
|
||||
or
|
||||
// Flow through an instance field between members of the same class
|
||||
DataFlow::localFieldStep(predNode, succ) and
|
||||
summary = level()
|
||||
)
|
||||
or
|
||||
DataFlow::localFieldStep(pred, succ) and
|
||||
summary = level()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +208,7 @@ private newtype TTypeBackTracker = MkTypeBackTracker(boolean hasReturn) {
|
||||
* ```
|
||||
* DataFlow::SourceNode myCallback(DataFlow::TypeBackTracker t) {
|
||||
* t.start() and
|
||||
* result = (< some API call >).getParameter(< n >).getALocalSource()
|
||||
* result = (< some API call >).getArgument(< n >).getALocalSource()
|
||||
* or
|
||||
* exists (DataFlow::TypeTracker t2 |
|
||||
* result = myCallback(t2).backtrack(t2, t)
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
test_ApiObject
|
||||
| tst.js:3:11:3:21 | new myapi() |
|
||||
| tst.js:15:10:15:21 | api.chain1() |
|
||||
| tst.js:15:10:15:30 | api.cha ... hain2() |
|
||||
test_Connection
|
||||
| tst.js:6:15:6:18 | conn |
|
||||
| tst.js:10:5:10:19 | this.connection |
|
||||
| tst.js:15:10:15:49 | api.cha ... ction() |
|
||||
| tst.js:18:7:18:21 | getConnection() |
|
||||
test_DataCallback
|
||||
| tst.js:9:11:9:12 | cb |
|
||||
| tst.js:20:1:22:1 | functio ... ata);\\n} |
|
||||
test_DataValue
|
||||
| tst.js:20:18:20:21 | data |
|
||||
| tst.js:24:19:24:22 | data |
|
||||
91
javascript/ql/test/library-tests/TypeTracking/ClassStyle.ql
Normal file
91
javascript/ql/test/library-tests/TypeTracking/ClassStyle.ql
Normal file
@@ -0,0 +1,91 @@
|
||||
import javascript
|
||||
|
||||
string chainableMethod() {
|
||||
result = "chain1" or
|
||||
result = "chain2"
|
||||
}
|
||||
|
||||
class ApiObject extends DataFlow::NewNode {
|
||||
ApiObject() {
|
||||
this = DataFlow::moduleImport("@test/myapi").getAnInstantiation()
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = this
|
||||
or
|
||||
t.start() and
|
||||
result = ref(_).getAMethodCall(chainableMethod())
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
result = ref(t2).track(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref() {
|
||||
result = ref(_)
|
||||
}
|
||||
}
|
||||
|
||||
class Connection extends DataFlow::SourceNode {
|
||||
ApiObject api;
|
||||
|
||||
Connection() {
|
||||
this = api.ref().getAMethodCall("createConnection")
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = this
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
result = ref(t2).track(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref() {
|
||||
result = ref(_)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode getACallbackNode(DataFlow::TypeBackTracker t) {
|
||||
t.start() and
|
||||
result = ref().getAMethodCall("getData").getArgument(0).getALocalSource()
|
||||
or
|
||||
exists(DataFlow::TypeBackTracker t2 |
|
||||
result = getACallbackNode(t2).backtrack(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::FunctionNode getACallback() {
|
||||
result = getACallbackNode(_).getAFunctionValue()
|
||||
}
|
||||
}
|
||||
|
||||
class DataValue extends DataFlow::SourceNode {
|
||||
Connection connection;
|
||||
|
||||
DataValue() {
|
||||
this = connection.getACallback().getParameter(0)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = this
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
result = ref(t2).track(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode ref() {
|
||||
result = ref(_)
|
||||
}
|
||||
}
|
||||
|
||||
query DataFlow::SourceNode test_ApiObject() { result = any(ApiObject obj).ref() }
|
||||
|
||||
query DataFlow::SourceNode test_Connection() { result = any(Connection c).ref() }
|
||||
|
||||
query DataFlow::SourceNode test_DataCallback() { result = any(Connection c).getACallbackNode(_) }
|
||||
|
||||
query DataFlow::SourceNode test_DataValue() { result = any(DataValue v).ref() }
|
||||
@@ -0,0 +1,15 @@
|
||||
apiObject
|
||||
| tst.js:3:11:3:21 | new myapi() |
|
||||
| tst.js:15:10:15:21 | api.chain1() |
|
||||
| tst.js:15:10:15:30 | api.cha ... hain2() |
|
||||
connection
|
||||
| type tracker with call steps | tst.js:6:15:6:18 | conn |
|
||||
| type tracker with call steps | tst.js:10:5:10:19 | this.connection |
|
||||
| type tracker without call steps | tst.js:15:10:15:49 | api.cha ... ction() |
|
||||
| type tracker without call steps | tst.js:18:7:18:21 | getConnection() |
|
||||
dataCallback
|
||||
| tst.js:9:11:9:12 | cb |
|
||||
| tst.js:20:1:22:1 | functio ... ata);\\n} |
|
||||
dataValue
|
||||
| tst.js:20:18:20:21 | data |
|
||||
| tst.js:24:19:24:22 | data |
|
||||
@@ -0,0 +1,61 @@
|
||||
import javascript
|
||||
|
||||
string chainableMethod() {
|
||||
result = "chain1" or
|
||||
result = "chain2"
|
||||
}
|
||||
|
||||
DataFlow::SourceNode apiObject(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = DataFlow::moduleImport("@test/myapi").getAnInstantiation()
|
||||
or
|
||||
t.start() and
|
||||
result = apiObject(_).getAMethodCall(chainableMethod())
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
result = apiObject(t2).track(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
query DataFlow::SourceNode apiObject() {
|
||||
result = apiObject(_)
|
||||
}
|
||||
|
||||
query DataFlow::SourceNode connection(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = apiObject().getAMethodCall("createConnection")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
result = connection(t2).track(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode connection() {
|
||||
result = connection(_)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode dataCallback(DataFlow::TypeBackTracker t) {
|
||||
t.start() and
|
||||
result = connection().getAMethodCall("getData").getArgument(0).getALocalSource()
|
||||
or
|
||||
exists(DataFlow::TypeBackTracker t2 |
|
||||
result = dataCallback(t2).backtrack(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
query DataFlow::SourceNode dataCallback() {
|
||||
result = dataCallback(_)
|
||||
}
|
||||
|
||||
DataFlow::SourceNode dataValue(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = dataCallback().getAFunctionValue().getParameter(0)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 |
|
||||
result = dataValue(t2).track(t2, t)
|
||||
)
|
||||
}
|
||||
|
||||
query DataFlow::SourceNode dataValue() {
|
||||
result = dataValue(_)
|
||||
}
|
||||
25
javascript/ql/test/library-tests/TypeTracking/tst.js
Normal file
25
javascript/ql/test/library-tests/TypeTracking/tst.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import myapi from "@test/myapi";
|
||||
|
||||
let api = new myapi();
|
||||
|
||||
class C {
|
||||
constructor(conn) {
|
||||
this.connection = conn;
|
||||
}
|
||||
getData(cb) {
|
||||
this.connection.getData(cb);
|
||||
}
|
||||
}
|
||||
|
||||
function getConnection() {
|
||||
return api.chain1().chain2().createConnection();
|
||||
}
|
||||
|
||||
new C(getConnection()).getData(useData);
|
||||
|
||||
function useData(data) {
|
||||
useData2(data);
|
||||
}
|
||||
|
||||
function useData2(data) {
|
||||
}
|
||||
Reference in New Issue
Block a user