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

Lines changed: 10 additions & 5 deletions
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
Lines changed: 5 additions & 0 deletions
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.
Lines changed: 0 additions & 1 deletion
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

Lines changed: 7 additions & 1 deletion
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)