mirror of
https://github.com/github/codeql.git
synced 2026-06-03 04:40:14 +02:00
Python: deprecate Function.getAReturnValueFlowNode() and rewrite internal callers
Follow-up to the getAFlowNode deprecation in the same PR: same AST→legacy-CFG bridge pattern. The 11 internal call sites (across objects/, types/, frameworks/, and TypeTrackingImpl) are rewritten to bind a `Return ret` explicitly, then constrain via `ret.getScope() = f and n.getNode() = ret.getValue()`. The predicate itself is preserved with a deprecation note so external users do not experience churn. Semantic noop. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `Function.getAReturnValueFlowNode()` predicate has been deprecated. Bind a `Return` node explicitly instead — `exists(Return ret | ret.getScope() = f and n.getNode() = ret.getValue())`. This is a preparatory step towards migrating the dataflow library off the legacy CFG; it has no semantic effect.
|
||||
@@ -153,8 +153,16 @@ class Function extends Function_, Scope, AstNode {
|
||||
|
||||
override predicate contains(AstNode inner) { Scope.super.contains(inner) }
|
||||
|
||||
/** Gets a control flow node for a return value of this function */
|
||||
ControlFlowNode getAReturnValueFlowNode() {
|
||||
/**
|
||||
* DEPRECATED: bind a `Return` node explicitly instead, e.g.
|
||||
* `exists(Return ret | ret.getScope() = this and n.getNode() = ret.getValue())`.
|
||||
* This API is being phased out together with `AstNode.getAFlowNode()` to
|
||||
* untangle the AST and CFG hierarchies in preparation for migrating the
|
||||
* dataflow library off the legacy CFG.
|
||||
*
|
||||
* Gets a control flow node for a return value of this function.
|
||||
*/
|
||||
deprecated ControlFlowNode getAReturnValueFlowNode() {
|
||||
exists(Return ret |
|
||||
ret.getScope() = this and
|
||||
ret.getValue() = result.getNode()
|
||||
|
||||
@@ -94,8 +94,10 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input {
|
||||
Node returnOf(Node callable, SummaryComponent return) {
|
||||
return = FlowSummaryImpl::Private::SummaryComponent::return() and
|
||||
// `result` should be the return value of a callable expression (lambda or function) referenced by `callable`
|
||||
result.asCfgNode() =
|
||||
callable.getALocalSource().asExpr().(CallableExpr).getInnerScope().getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = callable.getALocalSource().asExpr().(CallableExpr).getInnerScope() and
|
||||
result.asCfgNode().getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
// Relating callables to nodes
|
||||
|
||||
@@ -73,7 +73,10 @@ module Bottle {
|
||||
/** A response returned by a view callable. */
|
||||
class BottleReturnResponse extends Http::Server::HttpResponse::Range {
|
||||
BottleReturnResponse() {
|
||||
this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(View::ViewCallable vc) and
|
||||
this.asCfgNode().getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() { result = this }
|
||||
|
||||
@@ -2872,7 +2872,10 @@ module PrivateDjango {
|
||||
DataFlow::CfgNode
|
||||
{
|
||||
DjangoRedirectViewGetRedirectUrlReturn() {
|
||||
node = any(GetRedirectUrlFunction f).getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(GetRedirectUrlFunction f) and
|
||||
node.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getRedirectLocation() { result = this }
|
||||
|
||||
@@ -309,7 +309,10 @@ module FastApi {
|
||||
FastApiRouteSetup routeSetup;
|
||||
|
||||
FastApiRequestHandlerReturn() {
|
||||
node = routeSetup.getARequestHandler().getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = routeSetup.getARequestHandler() and
|
||||
node.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() { result = this }
|
||||
|
||||
@@ -166,7 +166,10 @@ module Pyramid {
|
||||
/** A response returned by a view callable. */
|
||||
private class PyramidReturnResponse extends Http::Server::HttpResponse::Range {
|
||||
PyramidReturnResponse() {
|
||||
this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode() and
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(View::ViewCallable vc) and
|
||||
this.asCfgNode().getNode() = ret.getValue()
|
||||
) and
|
||||
not this = instance()
|
||||
}
|
||||
|
||||
|
||||
@@ -2254,8 +2254,9 @@ module StdlibPrivate {
|
||||
DataFlow::CfgNode
|
||||
{
|
||||
WsgirefSimpleServerApplicationReturn() {
|
||||
exists(WsgirefSimpleServerApplication requestHandler |
|
||||
node = requestHandler.getAReturnValueFlowNode()
|
||||
exists(WsgirefSimpleServerApplication requestHandler, Return ret |
|
||||
ret.getScope() = requestHandler and
|
||||
node.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -182,7 +182,10 @@ private module Twisted {
|
||||
DataFlow::CfgNode
|
||||
{
|
||||
TwistedResourceRenderMethodReturn() {
|
||||
this.asCfgNode() = any(TwistedResourceRenderMethod meth).getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = any(TwistedResourceRenderMethod meth) and
|
||||
this.asCfgNode().getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getBody() { result = this }
|
||||
|
||||
@@ -81,11 +81,12 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
|
||||
|
||||
pragma[nomagic]
|
||||
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
|
||||
exists(Function func, ControlFlowNode rval, ControlFlowNode forigin |
|
||||
exists(Function func, Return ret, ControlFlowNode rval, ControlFlowNode forigin |
|
||||
func = this.getScope() and
|
||||
callee.appliesToScope(func)
|
||||
|
|
||||
rval = func.getAReturnValueFlowNode() and
|
||||
ret.getScope() = func and
|
||||
rval.getNode() = ret.getValue() and
|
||||
PointsToInternal::pointsTo(rval, callee, obj, forigin) and
|
||||
origin = CfgOrigin::fromCfgNode(forigin)
|
||||
)
|
||||
|
||||
@@ -745,7 +745,12 @@ class PythonFunctionValue extends FunctionValue {
|
||||
override int maxParameters() { result = this.getScope().getMaxPositionalArguments() }
|
||||
|
||||
/** Gets a control flow node corresponding to a return statement in this function */
|
||||
ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() }
|
||||
ControlFlowNode getAReturnedNode() {
|
||||
exists(Return ret |
|
||||
ret.getScope() = this.getScope() and
|
||||
result.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override ClassValue getARaisedType() { scope_raises(result, this.getScope()) }
|
||||
|
||||
|
||||
@@ -137,7 +137,10 @@ class PyFunctionObject extends FunctionObject {
|
||||
|
||||
/** Gets a control flow node corresponding to the value of a return statement */
|
||||
ControlFlowNodeWithPointsTo getAReturnedNode() {
|
||||
result = this.getFunction().getAReturnValueFlowNode()
|
||||
exists(Return ret |
|
||||
ret.getScope() = this.getFunction() and
|
||||
result.getNode() = ret.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override string descriptiveString() {
|
||||
|
||||
Reference in New Issue
Block a user