11
11
*/
12
12
13
13
import python
14
+ private import semmle.python.ApiGraphs
14
15
15
- FunctionValue iter ( ) { result = Value :: named ( "iter" ) }
16
+ API :: Node iter ( ) { result = API :: builtin ( "iter" ) }
16
17
17
- BuiltinFunctionValue next ( ) { result = Value:: named ( "next" ) }
18
+ API:: Node next ( ) { result = API:: builtin ( "next" ) }
19
+
20
+ API:: Node stopIteration ( ) { result = API:: builtin ( "StopIteration" ) }
18
21
19
22
predicate call_to_iter ( CallNode call , EssaVariable sequence ) {
20
- sequence .getAUse ( ) = iter ( ) .getArgumentForCall ( call , 0 )
23
+ call = iter ( ) .getACall ( ) .asCfgNode ( ) and
24
+ call .getArg ( 0 ) = sequence .getAUse ( )
21
25
}
22
26
23
27
predicate call_to_next ( CallNode call , ControlFlowNode iter ) {
24
- iter = next ( ) .getArgumentForCall ( call , 0 )
28
+ call = next ( ) .getACall ( ) .asCfgNode ( ) and
29
+ call .getArg ( 0 ) = iter
25
30
}
26
31
27
32
predicate call_to_next_has_default ( CallNode call ) {
@@ -47,7 +52,7 @@ predicate iter_not_exhausted(EssaVariable iterator) {
47
52
predicate stop_iteration_handled ( CallNode call ) {
48
53
exists ( Try t |
49
54
t .containsInScope ( call .getNode ( ) ) and
50
- t .getAHandler ( ) .getType ( ) . pointsTo ( ClassValue :: stopIteration ( ) )
55
+ t .getAHandler ( ) .getType ( ) = stopIteration ( ) . getAValueReachableFromSource ( ) . asExpr ( )
51
56
)
52
57
}
53
58
61
66
) and
62
67
call .getNode ( ) .getScope ( ) .( Function ) .isGenerator ( ) and
63
68
not exists ( Comp comp | comp .contains ( call .getNode ( ) ) ) and
64
- not stop_iteration_handled ( call )
69
+ not stop_iteration_handled ( call ) and
70
+ // PEP 479 removes this concern from 3.7 onwards
71
+ // see: https://peps.python.org/pep-0479/
72
+ //
73
+ // However, we do not know the minor version of the analyzed code (only of the extractor),
74
+ // so we only alert on Python 2.
75
+ major_version ( ) = 2
65
76
select call , "Call to next() in a generator"
0 commit comments