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)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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__` */
|
||||
predicate isInitMethod() { this.isMethod() and this.getName() = "__init__" }
|
||||
|
||||
|
||||
@@ -519,10 +519,12 @@ import ArgumentPassing
|
||||
*/
|
||||
newtype TDataFlowCallable =
|
||||
TCallableValue(CallableValue callable) {
|
||||
callable instanceof FunctionValue
|
||||
callable instanceof FunctionValue and
|
||||
not callable.(FunctionValue).isLambda()
|
||||
or
|
||||
callable instanceof ClassValue
|
||||
} or
|
||||
TLambda(Function lambda) { lambda.isLambda() } or
|
||||
TModule(Module m)
|
||||
|
||||
/** Represents a callable. */
|
||||
@@ -565,6 +567,27 @@ class DataFlowCallableValue extends DataFlowCallable, TCallableValue {
|
||||
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. */
|
||||
class DataFlowModuleScope extends DataFlowCallable, TModule {
|
||||
Module mod;
|
||||
|
||||
@@ -720,6 +720,9 @@ abstract class FunctionValue extends CallableValue {
|
||||
|
||||
/** Gets a class that this function may return */
|
||||
abstract ClassValue getAnInferredReturnType();
|
||||
|
||||
/** Holds if this function represents a lambda. */
|
||||
predicate isLambda() { this.getOrigin().getNode() instanceof Lambda }
|
||||
}
|
||||
|
||||
/** Class representing Python functions */
|
||||
|
||||
@@ -249,3 +249,10 @@ def synth_arg_kwOverflow():
|
||||
|
||||
def synth_arg_kwUnpacked():
|
||||
overflowCallee(**{"p": "42"})
|
||||
|
||||
def split_lambda(cond):
|
||||
if cond:
|
||||
pass
|
||||
foo = lambda x: False
|
||||
if cond:
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user