Skip to content

Commit befb51a

Browse files
yoffCopilot
andcommitted
Python: remove Function.getAReturnValueFlowNode() and rewrite callers
Follow-up to the getAFlowNode removal in the same PR: same AST→legacy-CFG bridge pattern. Rewrite the 11 call sites (across objects/, types/, frameworks/, and TypeTrackingImpl) to bind a `Return ret` explicitly, then constrain via `ret.getScope() = f and n.getNode() = ret.getValue()`. Semantic noop. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 0640250 commit befb51a

11 files changed

Lines changed: 40 additions & 21 deletions

File tree

python/ql/lib/semmle/python/Function.qll

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,6 @@ class Function extends Function_, Scope, AstNode {
153153

154154
override predicate contains(AstNode inner) { Scope.super.contains(inner) }
155155

156-
/** Gets a control flow node for a return value of this function */
157-
ControlFlowNode getAReturnValueFlowNode() {
158-
exists(Return ret |
159-
ret.getScope() = this and
160-
ret.getValue() = result.getNode()
161-
)
162-
}
163-
164156
/** Gets the minimum number of positional arguments that can be correctly passed to this function. */
165157
int getMinPositionalArguments() {
166158
result = count(this.getAnArg()) - count(this.getDefinition().getArgs().getADefault())

python/ql/lib/semmle/python/dataflow/new/internal/TypeTrackingImpl.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,10 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input {
9494
Node returnOf(Node callable, SummaryComponent return) {
9595
return = FlowSummaryImpl::Private::SummaryComponent::return() and
9696
// `result` should be the return value of a callable expression (lambda or function) referenced by `callable`
97-
result.asCfgNode() =
98-
callable.getALocalSource().asExpr().(CallableExpr).getInnerScope().getAReturnValueFlowNode()
97+
exists(Return ret |
98+
ret.getScope() = callable.getALocalSource().asExpr().(CallableExpr).getInnerScope() and
99+
result.asCfgNode().getNode() = ret.getValue()
100+
)
99101
}
100102

101103
// Relating callables to nodes

python/ql/lib/semmle/python/frameworks/Bottle.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ module Bottle {
7373
/** A response returned by a view callable. */
7474
class BottleReturnResponse extends Http::Server::HttpResponse::Range {
7575
BottleReturnResponse() {
76-
this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode()
76+
exists(Return ret |
77+
ret.getScope() = any(View::ViewCallable vc) and
78+
this.asCfgNode().getNode() = ret.getValue()
79+
)
7780
}
7881

7982
override DataFlow::Node getBody() { result = this }

python/ql/lib/semmle/python/frameworks/Django.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2872,7 +2872,10 @@ module PrivateDjango {
28722872
DataFlow::CfgNode
28732873
{
28742874
DjangoRedirectViewGetRedirectUrlReturn() {
2875-
node = any(GetRedirectUrlFunction f).getAReturnValueFlowNode()
2875+
exists(Return ret |
2876+
ret.getScope() = any(GetRedirectUrlFunction f) and
2877+
node.getNode() = ret.getValue()
2878+
)
28762879
}
28772880

28782881
override DataFlow::Node getRedirectLocation() { result = this }

python/ql/lib/semmle/python/frameworks/FastApi.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,10 @@ module FastApi {
309309
FastApiRouteSetup routeSetup;
310310

311311
FastApiRequestHandlerReturn() {
312-
node = routeSetup.getARequestHandler().getAReturnValueFlowNode()
312+
exists(Return ret |
313+
ret.getScope() = routeSetup.getARequestHandler() and
314+
node.getNode() = ret.getValue()
315+
)
313316
}
314317

315318
override DataFlow::Node getBody() { result = this }

python/ql/lib/semmle/python/frameworks/Pyramid.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@ module Pyramid {
166166
/** A response returned by a view callable. */
167167
private class PyramidReturnResponse extends Http::Server::HttpResponse::Range {
168168
PyramidReturnResponse() {
169-
this.asCfgNode() = any(View::ViewCallable vc).getAReturnValueFlowNode() and
169+
exists(Return ret |
170+
ret.getScope() = any(View::ViewCallable vc) and
171+
this.asCfgNode().getNode() = ret.getValue()
172+
) and
170173
not this = instance()
171174
}
172175

python/ql/lib/semmle/python/frameworks/Stdlib.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,8 +2254,9 @@ module StdlibPrivate {
22542254
DataFlow::CfgNode
22552255
{
22562256
WsgirefSimpleServerApplicationReturn() {
2257-
exists(WsgirefSimpleServerApplication requestHandler |
2258-
node = requestHandler.getAReturnValueFlowNode()
2257+
exists(WsgirefSimpleServerApplication requestHandler, Return ret |
2258+
ret.getScope() = requestHandler and
2259+
node.getNode() = ret.getValue()
22592260
)
22602261
}
22612262

python/ql/lib/semmle/python/frameworks/Twisted.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@ private module Twisted {
182182
DataFlow::CfgNode
183183
{
184184
TwistedResourceRenderMethodReturn() {
185-
this.asCfgNode() = any(TwistedResourceRenderMethod meth).getAReturnValueFlowNode()
185+
exists(Return ret |
186+
ret.getScope() = any(TwistedResourceRenderMethod meth) and
187+
this.asCfgNode().getNode() = ret.getValue()
188+
)
186189
}
187190

188191
override DataFlow::Node getBody() { result = this }

python/ql/lib/semmle/python/objects/Callables.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ class PythonFunctionObjectInternal extends CallableObjectInternal, TPythonFuncti
8181

8282
pragma[nomagic]
8383
override predicate callResult(PointsToContext callee, ObjectInternal obj, CfgOrigin origin) {
84-
exists(Function func, ControlFlowNode rval, ControlFlowNode forigin |
84+
exists(Function func, Return ret, ControlFlowNode rval, ControlFlowNode forigin |
8585
func = this.getScope() and
8686
callee.appliesToScope(func)
8787
|
88-
rval = func.getAReturnValueFlowNode() and
88+
ret.getScope() = func and
89+
rval.getNode() = ret.getValue() and
8990
PointsToInternal::pointsTo(rval, callee, obj, forigin) and
9091
origin = CfgOrigin::fromCfgNode(forigin)
9192
)

python/ql/lib/semmle/python/objects/ObjectAPI.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,12 @@ class PythonFunctionValue extends FunctionValue {
745745
override int maxParameters() { result = this.getScope().getMaxPositionalArguments() }
746746

747747
/** Gets a control flow node corresponding to a return statement in this function */
748-
ControlFlowNode getAReturnedNode() { result = this.getScope().getAReturnValueFlowNode() }
748+
ControlFlowNode getAReturnedNode() {
749+
exists(Return ret |
750+
ret.getScope() = this.getScope() and
751+
result.getNode() = ret.getValue()
752+
)
753+
}
749754

750755
override ClassValue getARaisedType() { scope_raises(result, this.getScope()) }
751756

0 commit comments

Comments
 (0)