]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-38640: Allow break and continue in always false while loops (GH-16992)
authorMiss Skeleton (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 30 Oct 2019 12:11:41 +0000 (05:11 -0700)
committerGitHub <noreply@github.com>
Wed, 30 Oct 2019 12:11:41 +0000 (05:11 -0700)
(cherry picked from commit 6c3e66a34b95fff07df0ad5086104dd637a091ce)

Co-authored-by: Pablo Galindo <Pablogsal@gmail.com>
Lib/test/test_compile.py
Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst [new file with mode: 0644]
Python/compile.c

index 9d77f7af05d6fd02ffb73abe0e8009d77412aceb..566ca27fca893da74b8f678479b9a8ca0a98ccb5 100644 (file)
@@ -731,6 +731,24 @@ if 1:
             self.assertEqual(None, opcodes[0].argval)
             self.assertEqual('RETURN_VALUE', opcodes[1].opname)
 
+    def test_false_while_loop(self):
+        def break_in_while():
+            while False:
+                break
+
+        def continue_in_while():
+            while False:
+                continue
+
+        funcs = [break_in_while, continue_in_while]
+
+        # Check that we did not raise but we also don't generate bytecode
+        for func in funcs:
+            opcodes = list(dis.get_instructions(func))
+            self.assertEqual(2, len(opcodes))
+            self.assertEqual('LOAD_CONST', opcodes[0].opname)
+            self.assertEqual(None, opcodes[0].argval)
+            self.assertEqual('RETURN_VALUE', opcodes[1].opname)
 
 class TestExpressionStackSize(unittest.TestCase):
     # These tests check that the computed stack size for a code object
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst b/Misc/NEWS.d/next/Core and Builtins/2019-10-30-11-25-25.bpo-38640.4sAFh5.rst
new file mode 100644 (file)
index 0000000..d99db3c
--- /dev/null
@@ -0,0 +1,3 @@
+Fixed a bug in the compiler that was causing to raise in the presence of
+break statements and continue statements inside always false while loops.
+Patch by Pablo Galindo.
index a512e9cbd13a16773bb017ea8239a07dfa5e6607..f09e99fd4a43d3c9af424522ce3b8167db47e56d 100644 (file)
@@ -2736,7 +2736,15 @@ compiler_while(struct compiler *c, stmt_ty s)
 
     if (constant == 0) {
         BEGIN_DO_NOT_EMIT_BYTECODE
+        // Push a dummy block so the VISIT_SEQ knows that we are
+        // inside a while loop so it can correctly evaluate syntax
+        // errors.
+        if (!compiler_push_fblock(c, WHILE_LOOP, NULL, NULL)) {
+            return 0;
+        }
         VISIT_SEQ(c, stmt, s->v.While.body);
+        // Remove the dummy block now that is not needed.
+        compiler_pop_fblock(c, WHILE_LOOP, NULL);
         END_DO_NOT_EMIT_BYTECODE
         if (s->v.While.orelse) {
             VISIT_SEQ(c, stmt, s->v.While.orelse);