]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-104615: don't make unsafe swaps in apply_static_swaps (GH-104620). (#104636)
authorCarl Meyer <carl@oddbird.net>
Fri, 19 May 2023 18:04:04 +0000 (12:04 -0600)
committerGitHub <noreply@github.com>
Fri, 19 May 2023 18:04:04 +0000 (12:04 -0600)
(cherry picked from commit 0589c6a4d3d822cace42050198cb9a5e99c879ad)

Lib/test/test_compile.py
Misc/NEWS.d/next/Core and Builtins/2023-05-18-13-00-21.gh-issue-104615.h_rtw2.rst [new file with mode: 0644]
Python/compile.c

index c96ae4375df88337aaec41c31f23703ad0e0644c..c756d43a3cf3b8376fcb881557973fc7803a7412 100644 (file)
@@ -1064,6 +1064,24 @@ if 1:
                 with self.subTest(source):
                     self.assertEqual(actual_positions, expected_positions)
 
+    def test_apply_static_swaps(self):
+        def f(x, y):
+            a, a = x, y
+            return a
+        self.assertEqual(f("x", "y"), "y")
+
+    def test_apply_static_swaps_2(self):
+        def f(x, y, z):
+            a, b, a = x, y, z
+            return a
+        self.assertEqual(f("x", "y", "z"), "z")
+
+    def test_apply_static_swaps_3(self):
+        def f(x, y, z):
+            a, a, b = x, y, z
+            return a
+        self.assertEqual(f("x", "y", "z"), "y")
+
 
 @requires_debug_ranges()
 class TestSourcePositions(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-05-18-13-00-21.gh-issue-104615.h_rtw2.rst b/Misc/NEWS.d/next/Core and Builtins/2023-05-18-13-00-21.gh-issue-104615.h_rtw2.rst
new file mode 100644 (file)
index 0000000..447291a
--- /dev/null
@@ -0,0 +1,2 @@
+Fix wrong ordering of assignments in code like ``a, a = x, y``. Contributed by
+Carl Meyer.
index f87a423acd1f025dc92654e73cab64d3d654c3f8..1c712fba31573e2dba4f3bb8c60adf9b69e7aa1c 100644 (file)
@@ -8690,6 +8690,9 @@ swaptimize(basicblock *block, int *ix)
 #define SWAPPABLE(opcode) \
     ((opcode) == STORE_FAST || (opcode) == POP_TOP)
 
+#define STORES_TO(instr) \
+    (((instr).i_opcode == STORE_FAST) ? (instr).i_oparg : -1)
+
 static int
 next_swappable_instruction(basicblock *block, int i, int lineno)
 {
@@ -8741,6 +8744,23 @@ apply_static_swaps(basicblock *block, int i)
                 return;
             }
         }
+        // The reordering is not safe if the two instructions to be swapped
+        // store to the same location, or if any intervening instruction stores
+        // to the same location as either of them.
+        int store_j = STORES_TO(block->b_instr[j]);
+        int store_k = STORES_TO(block->b_instr[k]);
+        if (store_j >= 0 || store_k >= 0) {
+            if (store_j == store_k) {
+                return;
+            }
+            for (int idx = j + 1; idx < k; idx++) {
+                int store_idx = STORES_TO(block->b_instr[idx]);
+                if (store_idx >= 0 && (store_idx == store_j || store_idx == store_k)) {
+                    return;
+                }
+            }
+        }
+
         // Success!
         swap->i_opcode = NOP;
         struct instr temp = block->b_instr[j];