Skip to content

Commit aacdc70

Browse files
authored
Merge pull request #19136 from github/tausbn/python-modernise-mixed-tuple-returns-query
Python: Modernize `py/mixed-tuple-returns`
2 parents ffb25b7 + 6674288 commit aacdc70

File tree

4 files changed

+22
-7
lines changed

4 files changed

+22
-7
lines changed

python/ql/src/Functions/ReturnConsistentTupleSizes.ql

+10-5
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,32 @@
44
* @kind problem
55
* @tags reliability
66
* maintainability
7+
* quality
78
* @problem.severity recommendation
89
* @sub-severity high
910
* @precision high
1011
* @id py/mixed-tuple-returns
1112
*/
1213

1314
import python
15+
import semmle.python.ApiGraphs
1416

15-
predicate returns_tuple_of_size(Function func, int size, AstNode origin) {
16-
exists(Return return, TupleValue val |
17+
predicate returns_tuple_of_size(Function func, int size, Tuple tuple) {
18+
exists(Return return, DataFlow::Node value |
19+
value.asExpr() = return.getValue() and
1720
return.getScope() = func and
18-
return.getValue().pointsTo(val, origin)
21+
any(DataFlow::LocalSourceNode n | n.asExpr() = tuple).flowsTo(value)
1922
|
20-
size = val.length()
23+
size = count(int n | exists(tuple.getElt(n)))
2124
)
2225
}
2326

2427
from Function func, int s1, int s2, AstNode t1, AstNode t2
2528
where
2629
returns_tuple_of_size(func, s1, t1) and
2730
returns_tuple_of_size(func, s2, t2) and
28-
s1 < s2
31+
s1 < s2 and
32+
// Don't report on functions that have a return type annotation
33+
not exists(func.getDefinition().(FunctionExpr).getReturns())
2934
select func, func.getQualifiedName() + " returns $@ and $@.", t1, "tuple of size " + s1, t2,
3035
"tuple of size " + s2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
5+
- The `py/mixed-tuple-returns` query no longer flags instances where the tuple is passed into the function as an argument, as this led to too many false positives.
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
11
| functions_test.py:306:1:306:39 | Function returning_different_tuple_sizes | returning_different_tuple_sizes returns $@ and $@. | functions_test.py:308:16:308:18 | Tuple | tuple of size 2 | functions_test.py:310:16:310:20 | Tuple | tuple of size 3 |
2-
| functions_test.py:324:1:324:50 | Function indirectly_returning_different_tuple_sizes | indirectly_returning_different_tuple_sizes returns $@ and $@. | functions_test.py:319:12:319:14 | Tuple | tuple of size 2 | functions_test.py:322:12:322:16 | Tuple | tuple of size 3 |

python/ql/test/query-tests/Functions/return_values/functions_test.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def function_returning_2_tuple():
321321
def function_returning_3_tuple():
322322
return 1,2,3
323323

324-
def indirectly_returning_different_tuple_sizes(x):
324+
def indirectly_returning_different_tuple_sizes(x): # OK, since we only look at local tuple returns
325325
if x:
326326
return function_returning_2_tuple()
327327
else:
@@ -347,3 +347,9 @@ def ok_match2(x): # FP
347347
return 0
348348
case _:
349349
return 1
350+
351+
def ok_tuple_returns_captured_in_type(x: bool) -> tuple[int, ...]: # OK because there is a type annotation present
352+
if x:
353+
return 1, 2
354+
else:
355+
return 1, 2, 3

0 commit comments

Comments
 (0)