mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
JS: Rewrite AnalyzedThisInArrayIterationFunction
This commit is contained in:
@@ -46,33 +46,26 @@ class DirectEval extends CallExpr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flow analysis for `this` expressions inside a function that is called with
|
* Models `Array.prototype.map` and friends as partial invocations that pass their second
|
||||||
* `Array.prototype.map` or a similar Array function that binds `this`.
|
* argument as the receiver to the callback.
|
||||||
*
|
|
||||||
* However, since the function could be invoked in another way, we additionally
|
|
||||||
* still infer the ordinary abstract value.
|
|
||||||
*/
|
*/
|
||||||
private class AnalyzedThisInArrayIterationFunction extends AnalyzedNode, DataFlow::ThisNode {
|
private class ArrayIterationCallbackAsPartialInvoke extends DataFlow::PartialInvokeNode::Range, DataFlow::MethodCallNode {
|
||||||
AnalyzedNode thisSource;
|
ArrayIterationCallbackAsPartialInvoke() {
|
||||||
|
getNumArgument() = 2 and
|
||||||
AnalyzedThisInArrayIterationFunction() {
|
// Filter out library methods named 'forEach' etc
|
||||||
exists(DataFlow::MethodCallNode bindingCall, string name |
|
not DataFlow::moduleImport(_).flowsTo(getReceiver()) and
|
||||||
|
exists(string name | name = getMethodName() |
|
||||||
name = "filter" or
|
name = "filter" or
|
||||||
name = "forEach" or
|
name = "forEach" or
|
||||||
name = "map" or
|
name = "map" or
|
||||||
name = "some" or
|
name = "some" or
|
||||||
name = "every"
|
name = "every"
|
||||||
|
|
|
||||||
name = bindingCall.getMethodName() and
|
|
||||||
2 = bindingCall.getNumArgument() and
|
|
||||||
getBinder() = bindingCall.getCallback(0) and
|
|
||||||
thisSource = bindingCall.getArgument(1)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AbstractValue getALocalValue() {
|
override DataFlow::Node getBoundReceiver(DataFlow::Node callback) {
|
||||||
result = thisSource.getALocalValue() or
|
callback = getArgument(0) and
|
||||||
result = AnalyzedNode.super.getALocalValue()
|
result = getArgument(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -274,3 +274,24 @@ private class TypeInferredMethodWithAnalyzedReturnFlow extends CallWithNonLocalA
|
|||||||
|
|
||||||
override AnalyzedFunction getACallee() { result = fun }
|
override AnalyzedFunction getACallee() { result = fun }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Propagates receivers into locally defined callbacks of partial invocations.
|
||||||
|
*/
|
||||||
|
private class AnalyzedThisInPartialInvokeCallback extends AnalyzedNode, DataFlow::ThisNode {
|
||||||
|
DataFlow::PartialInvokeNode call;
|
||||||
|
DataFlow::Node receiver;
|
||||||
|
|
||||||
|
AnalyzedThisInPartialInvokeCallback() {
|
||||||
|
exists(DataFlow::Node callbackArg |
|
||||||
|
receiver = call.getBoundReceiver(callbackArg) and
|
||||||
|
getBinder().flowsTo(callbackArg)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override AbstractValue getALocalValue() {
|
||||||
|
result = receiver.analyze().getALocalValue()
|
||||||
|
or
|
||||||
|
result = AnalyzedNode.super.getALocalValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user