mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
Python: remove NonLibraryNormalCall
it is not necessary to distinguish these calls, so we remove the class from the hierarchy.
This commit is contained in:
@@ -103,10 +103,10 @@ module ArgumentPassing {
|
||||
* Used to limit the size of predicates.
|
||||
*/
|
||||
predicate connects(CallNode call, CallableValue callable) {
|
||||
exists(NonLibraryNormalCall c, NonLibraryDataFlowCallable k |
|
||||
exists(NormalCall c, NonLibraryDataFlowCallable k |
|
||||
call = c.getNode() and
|
||||
callable = k.getCallableValue() and
|
||||
k = c.getNonLibraryCallable()
|
||||
k = c.getCallable()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -511,31 +511,20 @@ class NormalCall extends DataFlowSourceCall, TNormalCall {
|
||||
|
||||
abstract override Node getArg(int n);
|
||||
|
||||
override ControlFlowNode getNode() { result = call }
|
||||
override CallNode getNode() { result = call }
|
||||
|
||||
abstract override DataFlowCallable getCallable();
|
||||
|
||||
override DataFlowCallable getEnclosingCallable() { result.getScope() = call.getNode().getScope() }
|
||||
}
|
||||
|
||||
/** A (non-special) call that does not go to a library callable. */
|
||||
abstract class NonLibraryNormalCall extends NormalCall {
|
||||
abstract Node getNonLibraryArg(int n);
|
||||
|
||||
final override Node getArg(int n) { result = this.getNonLibraryArg(n) }
|
||||
|
||||
abstract DataFlowCallable getNonLibraryCallable();
|
||||
|
||||
final override DataFlowCallable getCallable() { result = this.getNonLibraryCallable() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a function.
|
||||
* This excludes calls to bound methods, classes, and special methods.
|
||||
* Bound method calls and class calls insert an argument for the explicit
|
||||
* `self` parameter, and special method calls have special argument passing.
|
||||
*/
|
||||
class FunctionCall extends NonLibraryNormalCall {
|
||||
class FunctionCall extends NormalCall {
|
||||
NonLibraryDataFlowCallable callable;
|
||||
|
||||
FunctionCall() {
|
||||
@@ -543,15 +532,13 @@ class FunctionCall extends NonLibraryNormalCall {
|
||||
call = callable.getACall()
|
||||
}
|
||||
|
||||
override Node getNonLibraryArg(int n) {
|
||||
result = getArg(call, TNoShift(), callable.getCallableValue(), n)
|
||||
}
|
||||
override Node getArg(int n) { result = getArg(call, TNoShift(), callable.getCallableValue(), n) }
|
||||
|
||||
override DataFlowCallable getNonLibraryCallable() { result = callable }
|
||||
override DataFlowCallable getCallable() { result = callable }
|
||||
}
|
||||
|
||||
/** A call to a lambda. */
|
||||
class LambdaCall extends NonLibraryNormalCall {
|
||||
class LambdaCall extends NormalCall {
|
||||
NonLibraryDataFlowCallable callable;
|
||||
|
||||
LambdaCall() {
|
||||
@@ -559,33 +546,29 @@ class LambdaCall extends NonLibraryNormalCall {
|
||||
callable = TLambda(any(Function f))
|
||||
}
|
||||
|
||||
override Node getNonLibraryArg(int n) {
|
||||
result = getArg(call, TNoShift(), callable.getCallableValue(), n)
|
||||
}
|
||||
override Node getArg(int n) { result = getArg(call, TNoShift(), callable.getCallableValue(), n) }
|
||||
|
||||
override DataFlowCallable getNonLibraryCallable() { result = callable }
|
||||
override DataFlowCallable getCallable() { result = callable }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a call to a bound method call.
|
||||
* The node representing the instance is inserted as argument to the `self` parameter.
|
||||
*/
|
||||
class MethodCall extends NonLibraryNormalCall {
|
||||
class MethodCall extends NormalCall {
|
||||
FunctionValue bm;
|
||||
|
||||
MethodCall() { call = bm.getAMethodCall() }
|
||||
|
||||
private CallableValue getCallableValue() { result = bm }
|
||||
|
||||
override Node getNonLibraryArg(int n) {
|
||||
override Node getArg(int n) {
|
||||
n > 0 and result = getArg(call, TShiftOneUp(), this.getCallableValue(), n)
|
||||
or
|
||||
n = 0 and result = TCfgNode(call.getFunction().(AttrNode).getObject())
|
||||
}
|
||||
|
||||
override DataFlowCallable getNonLibraryCallable() {
|
||||
result = TCallableValue(this.getCallableValue())
|
||||
}
|
||||
override DataFlowCallable getCallable() { result = TCallableValue(this.getCallableValue()) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -594,7 +577,7 @@ class MethodCall extends NonLibraryNormalCall {
|
||||
* That makes the call node be the post-update node holding the value of the object
|
||||
* after the constructor has run.
|
||||
*/
|
||||
class ClassCall extends NonLibraryNormalCall {
|
||||
class ClassCall extends NormalCall {
|
||||
ClassValue c;
|
||||
|
||||
ClassCall() {
|
||||
@@ -604,15 +587,13 @@ class ClassCall extends NonLibraryNormalCall {
|
||||
|
||||
private CallableValue getCallableValue() { c.getScope().getInitMethod() = result.getScope() }
|
||||
|
||||
override Node getNonLibraryArg(int n) {
|
||||
override Node getArg(int n) {
|
||||
n > 0 and result = getArg(call, TShiftOneUp(), this.getCallableValue(), n)
|
||||
or
|
||||
n = 0 and result = TSyntheticPreUpdateNode(TCfgNode(call))
|
||||
}
|
||||
|
||||
override DataFlowCallable getNonLibraryCallable() {
|
||||
result = TCallableValue(this.getCallableValue())
|
||||
}
|
||||
override DataFlowCallable getCallable() { result = TCallableValue(this.getCallableValue()) }
|
||||
}
|
||||
|
||||
/** A call to a special method. */
|
||||
|
||||
@@ -137,15 +137,15 @@ module SyntheticPostUpdateNode {
|
||||
* and should not have an extra node synthesised.
|
||||
*/
|
||||
Node argumentPreUpdateNode() {
|
||||
result = any(FunctionCall c).getNonLibraryArg(_)
|
||||
result = any(FunctionCall c).getArg(_)
|
||||
or
|
||||
// Avoid argument 0 of method calls as those have read post-update nodes.
|
||||
exists(MethodCall c, int n | n > 0 | result = c.getNonLibraryArg(n))
|
||||
exists(MethodCall c, int n | n > 0 | result = c.getArg(n))
|
||||
or
|
||||
result = any(SpecialCall c).getArg(_)
|
||||
or
|
||||
// Avoid argument 0 of class calls as those have non-synthetic post-update nodes.
|
||||
exists(ClassCall c, int n | n > 0 | result = c.getNonLibraryArg(n))
|
||||
exists(ClassCall c, int n | n > 0 | result = c.getArg(n))
|
||||
or
|
||||
// any argument of any call that we have not been able to resolve
|
||||
exists(CallNode call | not resolvedCall(call) |
|
||||
|
||||
@@ -11,15 +11,20 @@
|
||||
* These are identified by strings and has predicates for finding calls to them.
|
||||
*
|
||||
* Having both extracted and non-extracted callables means that we now have three types of calls:
|
||||
* - Extracted calls to extracted callables, either `NonLibraryNormalCall` or `SpecialCall`. These are handled by standard data flow.
|
||||
* - Extracted calls to non-extracted callables, `LibraryCall`. These are handled by summaries.
|
||||
* - Extracted calls to extracted callables, either `NormalCall` or `SpecialCall`. These are handled by standard data flow.
|
||||
* - Extracted calls to non-extracted callables, `LibraryCall`. These are handled by loking up the relevant summary when the
|
||||
* global data flwo graph is connected up via `getViableCallable`.
|
||||
* - Non-extracted calls, `SummaryCall`. These are synthesised by the flow summary framework.
|
||||
*
|
||||
* The first two can be referred to as `DataFlowSourceCall`. They have been split up for the benefit of call resolutiuon.
|
||||
* The first two can be referred to as `DataFlowSourceCall`. In fact, `LibraryCall` is a subclass of `NormalCall`, where
|
||||
* `getCallable` is set to `none()`. The member predicate `DataFlowSourceCall::getCallable` is _not_ the mechanism for
|
||||
* call resolution in global data flow. That mechanism is `getViableCallable`.
|
||||
* Resolving a call to a non-extracted callable goes via `LibraryCallable::getACall`, which may involve type tracking.
|
||||
* To avoid that type tracking becomes mutualy recursive with data flow, type tracking must use a call graph not including summaries.
|
||||
* Type tracking sees the callgraph given by `DataFlowSourceCall::getACallable`.
|
||||
*
|
||||
* We do not support summaries of special methods.
|
||||
* We do not support summaries of special methods via the special methods framework,
|
||||
* the summary would have to identify the call.
|
||||
*/
|
||||
|
||||
private import python
|
||||
|
||||
Reference in New Issue
Block a user