Skip to content

Commit e4f6f41

Browse files
committed
add DataFlow::getEnclosingExpr to get the an Expr from a potentially reflective call
1 parent 3a7f9a5 commit e4f6f41

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

javascript/ql/src/Statements/UseOfReturnlessFunction.ql

Lines changed: 2 additions & 2 deletions
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

Lines changed: 22 additions & 0 deletions
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

@@ -950,6 +962,16 @@ module DataFlow {
950962
* Gets a pseudo-node representing the root of a global access path.
951963
*/
952964
DataFlow::Node globalAccessPathRootPseudoNode() { result instanceof TGlobalAccessPathRoot }
965+
966+
/**
967+
* Gets a data flow node representing the underlying call performed by the given
968+
* call to `Function.prototype.call` or `Function.prototype.apply`.
969+
*
970+
* For example, for an expression `fn.call(x, y)`, this gets a call node with `fn` as the
971+
* callee, `x` as the receiver, and `y` as the first argument.
972+
*/
973+
DataFlow::InvokeNode reflectiveCallNode(InvokeExpr expr) { result = TReflectiveCallNode(expr, _) }
974+
953975

954976
/**
955977
* Provides classes representing various kinds of calls.

0 commit comments

Comments
 (0)