[Python-checkins] Fix a SystemError in code.replace() (#27771)

gvanrossum webhook-mailer at python.org
Mon Aug 16 14:34:45 EDT 2021


https://github.com/python/cpython/commit/62bd97303eb6d1fb0109e4a57d38c2ba6b0be7ff
commit: 62bd97303eb6d1fb0109e4a57d38c2ba6b0be7ff
branch: main
author: Guido van Rossum <guido at python.org>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2021-08-16T11:34:23-07:00
summary:

Fix a SystemError in code.replace() (#27771)

While the comment said 'We don't bother resizing localspluskinds',
this would cause .replace() to crash when it happened.
(Also types.CodeType(), but testing that is tedious, and this tests all
code paths.)

files:
M Lib/test/test_code.py
M Objects/codeobject.c

diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py
index 2bdd7e749434d..9d6b465115ca2 100644
--- a/Lib/test/test_code.py
+++ b/Lib/test/test_code.py
@@ -320,6 +320,15 @@ def func():
         with self.assertRaises(ValueError):
             co.replace(co_nlocals=co.co_nlocals + 1)
 
+    def test_shrinking_localsplus(self):
+        # Check that PyCode_NewWithPosOnlyArgs resizes both
+        # localsplusnames and localspluskinds, if an argument is a cell.
+        def func(arg):
+            return lambda: arg
+        code = func.__code__
+        newcode = code.replace(co_name="func")  # Should not raise SystemError
+        self.assertEqual(code, newcode)
+
     def test_empty_linetable(self):
         def func():
             pass
diff --git a/Objects/codeobject.c b/Objects/codeobject.c
index 3dc9fd787f385..ad8f13a781b94 100644
--- a/Objects/codeobject.c
+++ b/Objects/codeobject.c
@@ -471,9 +471,11 @@ PyCode_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount,
                                localsplusnames, localspluskinds);
     }
     // If any cells were args then nlocalsplus will have shrunk.
-    // We don't bother resizing localspluskinds.
-    if (_PyTuple_Resize(&localsplusnames, nlocalsplus) < 0) {
-        goto error;
+    if (nlocalsplus != PyTuple_GET_SIZE(localsplusnames)) {
+        if (_PyTuple_Resize(&localsplusnames, nlocalsplus) < 0
+                || _PyBytes_Resize(&localspluskinds, nlocalsplus) < 0) {
+            goto error;
+        }
     }
 
     struct _PyCodeConstructor con = {



More information about the Python-checkins mailing list