Skip to content

Commit b11a742

Browse files
authored
Merge pull request #2270 from erik-krogh/reflectiveExpr
Approved by max-schaefer
2 parents 9c97446 + 0c080a8 commit b11a742

File tree

4 files changed

+349
-2
lines changed

4 files changed

+349
-2
lines changed

javascript/ql/src/Statements/UseOfReturnlessFunction.ql

+2-2
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,9 @@ where
211211
msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + " is used." and
212212
name = "callback function"
213213
) and
214-
not benignContext(call.asExpr()) and
214+
not benignContext(call.getEnclosingExpr()) and
215215
not lastStatementHasNoEffect(func) and
216216
// anonymous one-shot closure. Those are used in weird ways and we ignore them.
217-
not oneshotClosure(call.asExpr())
217+
not oneshotClosure(call.getEnclosingExpr())
218218
select
219219
call, msg, func, name

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

+22
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,18 @@ module DataFlow {
8585
/** Gets the expression corresponding to this data flow node, if any. */
8686
Expr asExpr() { this = TValueNode(result) }
8787

88+
/**
89+
* Gets the expression enclosing this data flow node.
90+
* In most cases the result is the same as `asExpr()`, however this method
91+
* additionally the `InvokeExpr` corresponding to reflective calls, and the `Parameter`
92+
* for a `DataFlow::ParameterNode`.
93+
*/
94+
Expr getEnclosingExpr() {
95+
result = asExpr() or
96+
this = DataFlow::reflectiveCallNode(result) or
97+
result = this.(ParameterNode).getParameter()
98+
}
99+
88100
/** Gets the AST node corresponding to this data flow node, if any. */
89101
ASTNode getAstNode() { none() }
90102

@@ -983,6 +995,16 @@ module DataFlow {
983995
* Gets a pseudo-node representing the root of a global access path.
984996
*/
985997
DataFlow::Node globalAccessPathRootPseudoNode() { result instanceof TGlobalAccessPathRoot }
998+
999+
/**
1000+
* Gets a data flow node representing the underlying call performed by the given
1001+
* call to `Function.prototype.call` or `Function.prototype.apply`.
1002+
*
1003+
* For example, for an expression `fn.call(x, y)`, this gets a call node with `fn` as the
1004+
* callee, `x` as the receiver, and `y` as the first argument.
1005+
*/
1006+
DataFlow::InvokeNode reflectiveCallNode(InvokeExpr expr) { result = TReflectiveCallNode(expr, _) }
1007+
9861008

9871009
/**
9881010
* Gets a data flow node representing the underlying call performed by the given

0 commit comments

Comments
 (0)