mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
Merge pull request #5022 from yoff/python-split-lambdas
Python: Callable for lambdas
This commit is contained in:
@@ -39,6 +39,16 @@ class Function extends Function_, Scope, AstNode {
|
|||||||
exists(YieldFrom y | y.getScope() = this)
|
exists(YieldFrom y | y.getScope() = this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this function represents a lambda.
|
||||||
|
*
|
||||||
|
* The extractor reifies each lambda expression as a (local) function with the name
|
||||||
|
* "lambda". As `lambda` is a keyword in Python, it's impossible to create a function with this
|
||||||
|
* name otherwise, and so it's impossible to get a non-lambda function accidentally
|
||||||
|
* classified as a lambda.
|
||||||
|
*/
|
||||||
|
predicate isLambda() { this.getName() = "lambda" }
|
||||||
|
|
||||||
/** Whether this function is declared in a class and is named `__init__` */
|
/** Whether this function is declared in a class and is named `__init__` */
|
||||||
predicate isInitMethod() { this.isMethod() and this.getName() = "__init__" }
|
predicate isInitMethod() { this.isMethod() and this.getName() = "__init__" }
|
||||||
|
|
||||||
|
|||||||
@@ -519,10 +519,12 @@ import ArgumentPassing
|
|||||||
*/
|
*/
|
||||||
newtype TDataFlowCallable =
|
newtype TDataFlowCallable =
|
||||||
TCallableValue(CallableValue callable) {
|
TCallableValue(CallableValue callable) {
|
||||||
callable instanceof FunctionValue
|
callable instanceof FunctionValue and
|
||||||
|
not callable.(FunctionValue).isLambda()
|
||||||
or
|
or
|
||||||
callable instanceof ClassValue
|
callable instanceof ClassValue
|
||||||
} or
|
} or
|
||||||
|
TLambda(Function lambda) { lambda.isLambda() } or
|
||||||
TModule(Module m)
|
TModule(Module m)
|
||||||
|
|
||||||
/** Represents a callable. */
|
/** Represents a callable. */
|
||||||
@@ -565,6 +567,27 @@ class DataFlowCallableValue extends DataFlowCallable, TCallableValue {
|
|||||||
override CallableValue getCallableValue() { result = callable }
|
override CallableValue getCallableValue() { result = callable }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** A class representing a callable lambda. */
|
||||||
|
class DataFlowLambda extends DataFlowCallable, TLambda {
|
||||||
|
Function lambda;
|
||||||
|
|
||||||
|
DataFlowLambda() { this = TLambda(lambda) }
|
||||||
|
|
||||||
|
override string toString() { result = lambda.toString() }
|
||||||
|
|
||||||
|
override CallNode getACall() { result = getCallableValue().getACall() }
|
||||||
|
|
||||||
|
override Scope getScope() { result = lambda.getEvaluatingScope() }
|
||||||
|
|
||||||
|
override NameNode getParameter(int n) { result = getParameter(getCallableValue(), n) }
|
||||||
|
|
||||||
|
override string getName() { result = "Lambda callable" }
|
||||||
|
|
||||||
|
override FunctionValue getCallableValue() {
|
||||||
|
result.getOrigin().getNode() = lambda.getDefinition()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** A class representing the scope in which a `ModuleVariableNode` appears. */
|
/** A class representing the scope in which a `ModuleVariableNode` appears. */
|
||||||
class DataFlowModuleScope extends DataFlowCallable, TModule {
|
class DataFlowModuleScope extends DataFlowCallable, TModule {
|
||||||
Module mod;
|
Module mod;
|
||||||
|
|||||||
@@ -720,6 +720,9 @@ abstract class FunctionValue extends CallableValue {
|
|||||||
|
|
||||||
/** Gets a class that this function may return */
|
/** Gets a class that this function may return */
|
||||||
abstract ClassValue getAnInferredReturnType();
|
abstract ClassValue getAnInferredReturnType();
|
||||||
|
|
||||||
|
/** Holds if this function represents a lambda. */
|
||||||
|
predicate isLambda() { this.getOrigin().getNode() instanceof Lambda }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Class representing Python functions */
|
/** Class representing Python functions */
|
||||||
|
|||||||
@@ -249,3 +249,10 @@ def synth_arg_kwOverflow():
|
|||||||
|
|
||||||
def synth_arg_kwUnpacked():
|
def synth_arg_kwUnpacked():
|
||||||
overflowCallee(**{"p": "42"})
|
overflowCallee(**{"p": "42"})
|
||||||
|
|
||||||
|
def split_lambda(cond):
|
||||||
|
if cond:
|
||||||
|
pass
|
||||||
|
foo = lambda x: False
|
||||||
|
if cond:
|
||||||
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user