Merge pull request #9751 from erik-krogh/dynCall

JS: add call-edge for dynamic dispatch to unknown property from an object literal
This commit is contained in:
Erik Krogh Kristensen
2022-08-30 10:07:08 +02:00
committed by GitHub
8 changed files with 72 additions and 0 deletions

View File

@@ -89,6 +89,18 @@ module CallGraph {
result = getAFunctionReference(outer, 0, t.continue()).getAnInvocation() and
locallyReturnedFunction(outer, function)
)
or
// dynamic dispatch to unknown property of an object
exists(DataFlow::ObjectLiteralNode obj, DataFlow::PropRead read |
getAFunctionReference(function, 0, t.continue()) = obj.getAPropertySource() and
obj.getAPropertyRead() = read and
not exists(read.getPropertyName()) and
result = read and
// there exists only local reads of the object, nothing else.
forex(DataFlow::Node ref | ref = obj.getALocalUse() and exists(ref.asExpr()) |
ref = [obj, any(DataFlow::PropRead r).getBase()]
)
)
}
private predicate locallyReturnedFunction(

View File

@@ -910,7 +910,13 @@ getTypeExprType
| tst.ts:347:14:347:26 | State<number> | State<number> |
| tst.ts:347:20:347:25 | number | number |
| tst.ts:381:10:381:16 | SomeNum | 100 |
| tst.ts:381:20:381:24 | "100" | "100" |
| tst.ts:381:20:381:72 | "100" e ... : never | 100 |
| tst.ts:381:37:381:58 | infer U ... number | U |
| tst.ts:381:43:381:43 | U | U |
| tst.ts:381:53:381:58 | number | number |
| tst.ts:381:64:381:64 | U | U |
| tst.ts:381:68:381:72 | never | never |
| tst.ts:383:37:383:37 | T | T |
| tst.ts:383:43:383:43 | T | T |
| tst.ts:383:49:383:49 | T | T |

View File

@@ -27,6 +27,7 @@ test_RouteHandler_getAResponseHeader
| src/http.js:12:19:16:1 | functio ... ar");\\n} | content-type | src/http.js:13:3:13:44 | res.set ... /html') |
| src/https.js:4:33:10:1 | functio ... .foo;\\n} | location | src/https.js:7:3:7:42 | res.wri ... rget }) |
| src/https.js:12:20:16:1 | functio ... ar");\\n} | content-type | src/https.js:13:3:13:44 | res.set ... /html') |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | content-type | src/indirect2.js:14:3:14:51 | res.set ... /json') |
| src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | content-type | src/indirect2.js:14:3:14:51 | res.set ... /json') |
test_HeaderDefinition_defines
| src/http.js:13:3:13:44 | res.set ... /html') | content-type | text/html |
@@ -70,8 +71,11 @@ test_ResponseExpr
| src/https.js:15:3:15:5 | res | src/https.js:12:20:16:1 | functio ... ar");\\n} |
| src/indirect2.js:9:19:9:21 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:10:47:10:49 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:13:33:13:35 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:13:33:13:35 | res | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} |
| src/indirect2.js:14:3:14:5 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:14:3:14:5 | res | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} |
| src/indirect2.js:15:3:15:5 | res | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:15:3:15:5 | res | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} |
| src/indirect.js:16:26:16:28 | res | src/indirect.js:16:12:20:5 | functio ... ;\\n } |
| src/indirect.js:19:38:19:40 | res | src/indirect.js:16:12:20:5 | functio ... ;\\n } |
@@ -85,6 +89,7 @@ test_HeaderDefinition
| src/http.js:63:3:63:40 | res.set ... , "23") | src/http.js:62:19:65:1 | functio ... r2");\\n} |
| src/https.js:7:3:7:42 | res.wri ... rget }) | src/https.js:4:33:10:1 | functio ... .foo;\\n} |
| src/https.js:13:3:13:44 | res.set ... /html') | src/https.js:12:20:16:1 | functio ... ar");\\n} |
| src/indirect2.js:14:3:14:51 | res.set ... /json') | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:14:3:14:51 | res.set ... /json') | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} |
test_RouteSetup_getServer
| createServer.js:2:1:2:42 | https.c ... es) {}) | createServer.js:2:1:2:42 | https.c ... es) {}) |
@@ -171,6 +176,9 @@ test_RouteHandler_getAResponseExpr
| src/https.js:12:20:16:1 | functio ... ar");\\n} | src/https.js:15:3:15:5 | res |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:9:19:9:21 | res |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:10:47:10:49 | res |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:13:33:13:35 | res |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:14:3:14:5 | res |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:15:3:15:5 | res |
| src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:13:33:13:35 | res |
| src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:14:3:14:5 | res |
| src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:15:3:15:5 | res |
@@ -307,6 +315,7 @@ test_RequestExpr
| src/indirect2.js:9:14:9:16 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:10:12:10:14 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:10:42:10:44 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:13:28:13:30 | req | src/indirect2.js:9:1:11:1 | functio ... res);\\n} |
| src/indirect2.js:13:28:13:30 | req | src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} |
| src/indirect.js:16:21:16:23 | req | src/indirect.js:16:12:20:5 | functio ... ;\\n } |
| src/indirect.js:17:28:17:30 | req | src/indirect.js:16:12:20:5 | functio ... ;\\n } |
@@ -349,6 +358,7 @@ test_RouteHandler_getARequestExpr
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:9:14:9:16 | req |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:10:12:10:14 | req |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:10:42:10:44 | req |
| src/indirect2.js:9:1:11:1 | functio ... res);\\n} | src/indirect2.js:13:28:13:30 | req |
| src/indirect2.js:13:1:16:1 | functio ... \\"");\\n} | src/indirect2.js:13:28:13:30 | req |
| src/indirect.js:16:12:20:5 | functio ... ;\\n } | src/indirect.js:16:21:16:23 | req |
| src/indirect.js:16:12:20:5 | functio ... ;\\n } | src/indirect.js:17:28:17:30 | req |

View File

@@ -134,6 +134,12 @@ nodes
| form-parsers.js:59:10:59:33 | "touch ... ilename |
| form-parsers.js:59:21:59:24 | part |
| form-parsers.js:59:21:59:33 | part.filename |
| lib/subLib4/index.js:6:32:6:35 | name |
| lib/subLib4/index.js:7:18:7:21 | name |
| lib/subLib4/subsub.js:3:28:3:31 | name |
| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name |
| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name |
| lib/subLib4/subsub.js:4:22:4:25 | name |
| lib/subLib/index.js:7:32:7:35 | name |
| lib/subLib/index.js:8:10:8:25 | "rm -rf " + name |
| lib/subLib/index.js:8:10:8:25 | "rm -rf " + name |
@@ -232,6 +238,8 @@ edges
| child_process-test.js:73:25:73:31 | req.url | child_process-test.js:73:15:73:38 | url.par ... , true) |
| child_process-test.js:73:25:73:31 | req.url | child_process-test.js:73:15:73:38 | url.par ... , true) |
| child_process-test.js:83:19:83:36 | req.query.fileName | child_process-test.js:83:19:83:36 | req.query.fileName |
| child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib4/index.js:6:32:6:35 | name |
| child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib4/index.js:6:32:6:35 | name |
| child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:7:32:7:35 | name |
| child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:7:32:7:35 | name |
| child_process-test.js:94:21:94:30 | ctx.params | child_process-test.js:94:21:94:35 | ctx.params.host |
@@ -306,6 +314,11 @@ edges
| form-parsers.js:59:21:59:24 | part | form-parsers.js:59:21:59:33 | part.filename |
| form-parsers.js:59:21:59:33 | part.filename | form-parsers.js:59:10:59:33 | "touch ... ilename |
| form-parsers.js:59:21:59:33 | part.filename | form-parsers.js:59:10:59:33 | "touch ... ilename |
| lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/index.js:7:18:7:21 | name |
| lib/subLib4/index.js:7:18:7:21 | name | lib/subLib4/subsub.js:3:28:3:31 | name |
| lib/subLib4/subsub.js:3:28:3:31 | name | lib/subLib4/subsub.js:4:22:4:25 | name |
| lib/subLib4/subsub.js:4:22:4:25 | name | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name |
| lib/subLib4/subsub.js:4:22:4:25 | name | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name |
| lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name |
| lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name |
| lib/subLib/index.js:8:22:8:25 | name | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name |
@@ -385,6 +398,7 @@ edges
| form-parsers.js:41:10:41:31 | "touch ... ds.name | form-parsers.js:40:26:40:31 | fields | form-parsers.js:41:10:41:31 | "touch ... ds.name | $@ flows to here and is used in a command. | form-parsers.js:40:26:40:31 | fields | a user-provided value |
| form-parsers.js:53:10:53:31 | "touch ... ds.name | form-parsers.js:52:34:52:39 | fields | form-parsers.js:53:10:53:31 | "touch ... ds.name | $@ flows to here and is used in a command. | form-parsers.js:52:34:52:39 | fields | a user-provided value |
| form-parsers.js:59:10:59:33 | "touch ... ilename | form-parsers.js:58:30:58:33 | part | form-parsers.js:59:10:59:33 | "touch ... ilename | $@ flows to here and is used in a command. | form-parsers.js:58:30:58:33 | part | a user-provided value |
| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | $@ flows to here and is used in a command. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value |
| lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | child_process-test.js:85:37:85:54 | req.query.fileName | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | $@ flows to here and is used in a command. | child_process-test.js:85:37:85:54 | req.query.fileName | a user-provided value |
| other.js:7:33:7:35 | cmd | other.js:5:25:5:31 | req.url | other.js:7:33:7:35 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value |
| other.js:8:28:8:30 | cmd | other.js:5:25:5:31 | req.url | other.js:8:28:8:30 | cmd | $@ flows to here and is used in a command. | other.js:5:25:5:31 | req.url | a user-provided value |

View File

@@ -284,6 +284,12 @@ nodes
| lib/subLib3/my-file.ts:3:28:3:31 | name |
| lib/subLib3/my-file.ts:4:22:4:25 | name |
| lib/subLib3/my-file.ts:4:22:4:25 | name |
| lib/subLib4/index.js:6:32:6:35 | name |
| lib/subLib4/index.js:6:32:6:35 | name |
| lib/subLib4/index.js:7:18:7:21 | name |
| lib/subLib4/subsub.js:3:28:3:31 | name |
| lib/subLib4/subsub.js:4:22:4:25 | name |
| lib/subLib4/subsub.js:4:22:4:25 | name |
| lib/subLib/amdSub.js:3:28:3:31 | name |
| lib/subLib/amdSub.js:3:28:3:31 | name |
| lib/subLib/amdSub.js:4:22:4:25 | name |
@@ -640,6 +646,11 @@ edges
| lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name |
| lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name |
| lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name |
| lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/index.js:7:18:7:21 | name |
| lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/index.js:7:18:7:21 | name |
| lib/subLib4/index.js:7:18:7:21 | name | lib/subLib4/subsub.js:3:28:3:31 | name |
| lib/subLib4/subsub.js:3:28:3:31 | name | lib/subLib4/subsub.js:4:22:4:25 | name |
| lib/subLib4/subsub.js:3:28:3:31 | name | lib/subLib4/subsub.js:4:22:4:25 | name |
| lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name |
| lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name |
| lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name |
@@ -735,6 +746,7 @@ edges
| lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | lib/subLib2/compiled-file.ts:3:26:3:29 | name | lib/subLib2/compiled-file.ts:4:25:4:28 | name | $@ based on $@ is later used in $@. | lib/subLib2/compiled-file.ts:4:13:4:28 | "rm -rf " + name | String concatenation | lib/subLib2/compiled-file.ts:3:26:3:29 | name | library input | lib/subLib2/compiled-file.ts:4:5:4:29 | cp.exec ... + name) | shell command |
| lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | lib/subLib2/special-file.js:3:28:3:31 | name | lib/subLib2/special-file.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib2/special-file.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib2/special-file.js:3:28:3:31 | name | library input | lib/subLib2/special-file.js:4:2:4:26 | cp.exec ... + name) | shell command |
| lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | lib/subLib3/my-file.ts:3:28:3:31 | name | lib/subLib3/my-file.ts:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib3/my-file.ts:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib3/my-file.ts:3:28:3:31 | name | library input | lib/subLib3/my-file.ts:4:2:4:26 | cp.exec ... + name) | shell command |
| lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | lib/subLib4/index.js:6:32:6:35 | name | lib/subLib4/subsub.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib4/subsub.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib4/index.js:6:32:6:35 | name | library input | lib/subLib4/subsub.js:4:2:4:26 | cp.exec ... + name) | shell command |
| lib/subLib/amdSub.js:4:10:4:25 | "rm -rf " + name | lib/subLib/amdSub.js:3:28:3:31 | name | lib/subLib/amdSub.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib/amdSub.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib/amdSub.js:3:28:3:31 | name | library input | lib/subLib/amdSub.js:4:2:4:26 | cp.exec ... + name) | shell command |
| lib/subLib/index.js:4:10:4:25 | "rm -rf " + name | lib/subLib/index.js:3:28:3:31 | name | lib/subLib/index.js:4:22:4:25 | name | $@ based on $@ is later used in $@. | lib/subLib/index.js:4:10:4:25 | "rm -rf " + name | String concatenation | lib/subLib/index.js:3:28:3:31 | name | library input | lib/subLib/index.js:4:2:4:26 | cp.exec ... + name) | shell command |
| lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | lib/subLib/index.js:7:32:7:35 | name | lib/subLib/index.js:8:22:8:25 | name | $@ based on $@ is later used in $@. | lib/subLib/index.js:8:10:8:25 | "rm -rf " + name | String concatenation | lib/subLib/index.js:7:32:7:35 | name | library input | lib/subLib/index.js:8:2:8:26 | cp.exec ... + name) | shell command |

View File

@@ -0,0 +1,8 @@
const dispatch = {
GET: require("./bla"),
POST: require("./subsub"),
};
module.exports.foo = function (name, type) {
dispatch[type](name);
};

View File

@@ -0,0 +1,5 @@
{
"name": "my-sub-lib",
"version": "0.0.7",
"main": "./index.js"
}

View File

@@ -0,0 +1,5 @@
const cp = require("child_process")
module.exports = function (name) {
cp.exec("rm -rf " + name); // NOT OK - functions exported as part of a submodule are also flagged.
};