]> granicus.if.org Git - python/commitdiff
bpo-1875: Raise SyntaxError in invalid blocks that will be optimised away (GH-13332)
authorPablo Galindo <Pablogsal@gmail.com>
Fri, 17 May 2019 10:37:08 +0000 (11:37 +0100)
committerGitHub <noreply@github.com>
Fri, 17 May 2019 10:37:08 +0000 (11:37 +0100)
Move the check for dead conditionals (if 0) to the peephole optimizer
and make sure that the code block is still compiled to report any
existing syntax errors within.

Lib/test/test_syntax.py
Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst [new file with mode: 0644]
Python/compile.c
Python/peephole.c

index 4a2899ebca30802a267d9eee122a6febea57dd4f..8451c072f64209b2541081eb5229b0a27dd86fc0 100644 (file)
@@ -696,6 +696,20 @@ class SyntaxTestCase(unittest.TestCase):
     def test_break_outside_loop(self):
         self._check_error("break", "outside loop")
 
+    def test_yield_outside_function(self):
+        self._check_error("if 0: yield",               "outside function")
+        self._check_error("class C:\n    if 0: yield", "outside function")
+
+    def test_return_outside_function(self):
+        self._check_error("if 0: return",               "outside function")
+        self._check_error("class C:\n    if 0: return", "outside function")
+
+    def test_break_outside_loop(self):
+        self._check_error("if 0: break",                "outside loop")
+
+    def test_continue_outside_loop(self):
+        self._check_error("if 0: continue",     "not properly in loop")
+
     def test_unexpected_indent(self):
         self._check_error("foo()\n bar()\n", "unexpected indent",
                           subclass=IndentationError)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst b/Misc/NEWS.d/next/Core and Builtins/2019-05-15-01-29-29.bpo-1875.9oxXFX.rst
new file mode 100644 (file)
index 0000000..8f095ed
--- /dev/null
@@ -0,0 +1,3 @@
+A :exc:`SyntaxError` is now raised if a code blocks that will be optimized
+away (e.g. if conditions that are always false) contains syntax errors.
+Patch by Pablo Galindo.
index 91ce04b02e53c95c7af2046a61d9829b1d89eb6f..2a086a509f4595cdfc611a07013fa777483e6f23 100644 (file)
@@ -2546,13 +2546,12 @@ compiler_if(struct compiler *c, stmt_ty s)
         return 0;
 
     constant = expr_constant(s->v.If.test);
-    /* constant = 0: "if 0"
+    /* constant = 0: "if 0" Leave the optimizations to
+     * the pephole optimizer to check for syntax errors
+     * in the block.
      * constant = 1: "if 1", "if 2", ...
      * constant = -1: rest */
-    if (constant == 0) {
-        if (s->v.If.orelse)
-            VISIT_SEQ(c, stmt, s->v.If.orelse);
-    } else if (constant == 1) {
+    if (constant == 1) {
         VISIT_SEQ(c, stmt, s->v.If.body);
     } else {
         if (asdl_seq_LEN(s->v.If.orelse)) {
index cc244aa433ee1869593dc88d6e372fd2a803f817..1ce3535626e9a6bdfba220c29ee2175c6dcfc5ee 100644 (file)
@@ -302,11 +302,19 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
             case LOAD_CONST:
                 cumlc = lastlc + 1;
                 if (nextop != POP_JUMP_IF_FALSE  ||
-                    !ISBASICBLOCK(blocks, op_start, i + 1)  ||
-                    !PyObject_IsTrue(PyList_GET_ITEM(consts, get_arg(codestr, i))))
+                    !ISBASICBLOCK(blocks, op_start, i + 1)) {
                     break;
-                fill_nops(codestr, op_start, nexti + 1);
-                cumlc = 0;
+                }
+                PyObject* cnt = PyList_GET_ITEM(consts, get_arg(codestr, i));
+                int is_true = PyObject_IsTrue(cnt);
+                if (is_true == 1) {
+                    fill_nops(codestr, op_start, nexti + 1);
+                    cumlc = 0;
+                } else if (is_true == 0) {
+                    h = get_arg(codestr, nexti) / sizeof(_Py_CODEUNIT);
+                    tgt = find_op(codestr, codelen, h);
+                    fill_nops(codestr, op_start, tgt);
+                }
                 break;
 
                 /* Try to fold tuples of constants.