1111 */
1212
1313import python
14+ private import semmle.python.ApiGraphs
1415
15- FunctionValue iter ( ) { result = Value :: named ( "iter" ) }
16+ API :: Node iter ( ) { result = API :: builtin ( "iter" ) }
1617
17- BuiltinFunctionValue next ( ) { result = Value:: named ( "next" ) }
18+ API:: Node next ( ) { result = API:: builtin ( "next" ) }
19+
20+ API:: Node stopIteration ( ) { result = API:: builtin ( "StopIteration" ) }
1821
1922predicate 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 ( )
2125}
2226
2327predicate call_to_next ( CallNode call , ControlFlowNode iter ) {
24- iter = next ( ) .getArgumentForCall ( call , 0 )
28+ call = next ( ) .getACall ( ) .asCfgNode ( ) and
29+ call .getArg ( 0 ) = iter
2530}
2631
2732predicate call_to_next_has_default ( CallNode call ) {
@@ -47,7 +52,7 @@ predicate iter_not_exhausted(EssaVariable iterator) {
4752predicate stop_iteration_handled ( CallNode call ) {
4853 exists ( Try t |
4954 t .containsInScope ( call .getNode ( ) ) and
50- t .getAHandler ( ) .getType ( ) . pointsTo ( ClassValue :: stopIteration ( ) )
55+ t .getAHandler ( ) .getType ( ) = stopIteration ( ) . getAValueReachableFromSource ( ) . asExpr ( )
5156 )
5257}
5358
6166 ) and
6267 call .getNode ( ) .getScope ( ) .( Function ) .isGenerator ( ) and
6368 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
6576select call , "Call to next() in a generator"
0 commit comments