aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/codeobject.c
diff options
context:
space:
mode:
authorJelle Zijlstra <jelle.zijlstra@gmail.com>2023-11-08 12:11:59 -0800
committerGitHub <noreply@github.com>2023-11-08 13:11:59 -0700
commit0b718e6407da65b838576a2459d630824ca62155 (patch)
tree8947c7a8af9ec58b64c8ca37baf8791071c76912 /Objects/codeobject.c
parent804575b5c05f1dc94ccfebf6c5736d95410a0f01 (diff)
downloadcpython-0b718e6407da65b838576a2459d630824ca62155.tar.gz
cpython-0b718e6407da65b838576a2459d630824ca62155.zip
gh-110543: Fix CodeType.replace in presence of comprehensions (#110586)
Diffstat (limited to 'Objects/codeobject.c')
-rw-r--r--Objects/codeobject.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 79ac5749037..dc46b773c26 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -643,6 +643,35 @@ PyUnstable_Code_NewWithPosOnlyArgs(
_Py_set_localsplus_info(offset, name, CO_FAST_FREE,
localsplusnames, localspluskinds);
}
+
+ // gh-110543: Make sure the CO_FAST_HIDDEN flag is set correctly.
+ if (!(flags & CO_OPTIMIZED)) {
+ Py_ssize_t code_len = PyBytes_GET_SIZE(code);
+ _Py_CODEUNIT *code_data = (_Py_CODEUNIT *)PyBytes_AS_STRING(code);
+ Py_ssize_t num_code_units = code_len / sizeof(_Py_CODEUNIT);
+ int extended_arg = 0;
+ for (int i = 0; i < num_code_units; i += 1 + _PyOpcode_Caches[code_data[i].op.code]) {
+ _Py_CODEUNIT *instr = &code_data[i];
+ uint8_t opcode = instr->op.code;
+ if (opcode == EXTENDED_ARG) {
+ extended_arg = extended_arg << 8 | instr->op.arg;
+ continue;
+ }
+ if (opcode == LOAD_FAST_AND_CLEAR) {
+ int oparg = extended_arg << 8 | instr->op.arg;
+ if (oparg >= nlocalsplus) {
+ PyErr_Format(PyExc_ValueError,
+ "code: LOAD_FAST_AND_CLEAR oparg %d out of range",
+ oparg);
+ goto error;
+ }
+ _PyLocals_Kind kind = _PyLocals_GetKind(localspluskinds, oparg);
+ _PyLocals_SetKind(localspluskinds, oparg, kind | CO_FAST_HIDDEN);
+ }
+ extended_arg = 0;
+ }
+ }
+
// If any cells were args then nlocalsplus will have shrunk.
if (nlocalsplus != PyTuple_GET_SIZE(localsplusnames)) {
if (_PyTuple_Resize(&localsplusnames, nlocalsplus) < 0