summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorCarl Meyer <carl@oddbird.net>2023-05-18 21:22:03 (GMT)
committerGitHub <noreply@github.com>2023-05-18 21:22:03 (GMT)
commit0589c6a4d3d822cace42050198cb9a5e99c879ad (patch)
treeae6785cbe277413976d6513d80f42206477d5f0b /Python
parentdcdc90d384723920e8dea0ee04eae8c219333634 (diff)
downloadcpython-0589c6a4d3d822cace42050198cb9a5e99c879ad.zip
cpython-0589c6a4d3d822cace42050198cb9a5e99c879ad.tar.gz
cpython-0589c6a4d3d822cace42050198cb9a5e99c879ad.tar.bz2
gh-104615: don't make unsafe swaps in apply_static_swaps (#104620)
Diffstat (limited to 'Python')
-rw-r--r--Python/compile.c4
-rw-r--r--Python/flowgraph.c22
2 files changed, 24 insertions, 2 deletions
diff --git a/Python/compile.c b/Python/compile.c
index 07f8d66..96cd6da 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -7996,7 +7996,7 @@ finally:
}
PyObject *
-_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts)
+_PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts, int nlocals)
{
PyObject *res = NULL;
PyObject *const_cache = PyDict_New();
@@ -8008,7 +8008,7 @@ _PyCompile_OptimizeCfg(PyObject *instructions, PyObject *consts)
if (instructions_to_cfg(instructions, &g) < 0) {
goto error;
}
- int code_flags = 0, nlocals = 0, nparams = 0, firstlineno = 1;
+ int code_flags = 0, nparams = 0, firstlineno = 1;
if (_PyCfg_OptimizeCodeUnit(&g, consts, const_cache, code_flags, nlocals,
nparams, firstlineno) < 0) {
goto error;
diff --git a/Python/flowgraph.c b/Python/flowgraph.c
index 7f790b7..f8039a4 100644
--- a/Python/flowgraph.c
+++ b/Python/flowgraph.c
@@ -1293,6 +1293,11 @@ swaptimize(basicblock *block, int *ix)
(opcode) == STORE_FAST_MAYBE_NULL || \
(opcode) == POP_TOP)
+#define STORES_TO(instr) \
+ (((instr).i_opcode == STORE_FAST || \
+ (instr).i_opcode == STORE_FAST_MAYBE_NULL) \
+ ? (instr).i_oparg : -1)
+
static int
next_swappable_instruction(basicblock *block, int i, int lineno)
{
@@ -1344,6 +1349,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!
INSTR_SET_OP0(swap, NOP);
cfg_instr temp = block->b_instr[j];