mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
JavaScript: Teach API graphs to recognise arguments supplied in partial function applications.
This commit is contained in:
@@ -412,16 +412,9 @@ module API {
|
||||
rhs = f.getAReturn()
|
||||
)
|
||||
or
|
||||
exists(DataFlow::SourceNode src, DataFlow::InvokeNode invk |
|
||||
use(base, src) and invk = trackUseNode(src).getAnInvocation()
|
||||
|
|
||||
exists(int i |
|
||||
lbl = Label::parameter(i) and
|
||||
rhs = invk.getArgument(i)
|
||||
)
|
||||
or
|
||||
lbl = Label::receiver() and
|
||||
rhs = invk.(DataFlow::CallNode).getReceiver()
|
||||
exists(int i |
|
||||
lbl = Label::parameter(i) and
|
||||
argumentPassing(base, i, rhs)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::SourceNode src, DataFlow::PropWrite pw |
|
||||
@@ -432,6 +425,30 @@ module API {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is passed as the `i`th argument to a use of `base`, either by means of a
|
||||
* full invocation, or in a partial function application.
|
||||
*
|
||||
* The receiver is considered to be argument -1.
|
||||
*/
|
||||
private predicate argumentPassing(TApiNode base, int i, DataFlow::Node arg) {
|
||||
exists(DataFlow::SourceNode use, DataFlow::SourceNode pred |
|
||||
use(base, use) and pred = trackUseNode(use)
|
||||
|
|
||||
arg = pred.getAnInvocation().getArgument(i)
|
||||
or
|
||||
arg = pred.getACall().getReceiver() and
|
||||
i = -1
|
||||
or
|
||||
exists(DataFlow::PartialInvokeNode pin, DataFlow::Node callback | pred.flowsTo(callback) |
|
||||
pin.isPartialArgument(callback, arg, i)
|
||||
or
|
||||
arg = pin.getBoundReceiver(callback) and
|
||||
i = -1
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `rhs` is the right-hand side of a definition of node `nd`.
|
||||
*/
|
||||
@@ -719,10 +736,14 @@ private module Label {
|
||||
bindingset[s]
|
||||
string parameterByStringIndex(string s) {
|
||||
result = "parameter " + s and
|
||||
s.toInt() >= 0
|
||||
s.toInt() >= -1
|
||||
}
|
||||
|
||||
/** Gets the `parameter` edge label for the `i`th parameter. */
|
||||
/**
|
||||
* Gets the `parameter` edge label for the `i`th parameter.
|
||||
*
|
||||
* The receiver is considered to be parameter -1.
|
||||
*/
|
||||
bindingset[i]
|
||||
string parameter(int i) { result = parameterByStringIndex(i.toString()) }
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
import ApiGraphs.VerifyAssertions
|
||||
8
javascript/ql/test/ApiGraphs/partial-invoke/index.js
Normal file
8
javascript/ql/test/ApiGraphs/partial-invoke/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const cp = require('child_process');
|
||||
|
||||
module.exports = function () {
|
||||
return cp.spawn.bind(
|
||||
cp, // def (parameter -1 (member spawn (member exports (module child_process))))
|
||||
"cat" // def (parameter 0 (member spawn (member exports (module child_process))))
|
||||
);
|
||||
};
|
||||
3
javascript/ql/test/ApiGraphs/partial-invoke/package.json
Normal file
3
javascript/ql/test/ApiGraphs/partial-invoke/package.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"name": "partial-invoke"
|
||||
}
|
||||
Reference in New Issue
Block a user