summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2021-08-16 11:34:23 -0700
committerGitHub <noreply@github.com>2021-08-16 11:34:23 -0700
commit62bd97303eb6d1fb0109e4a57d38c2ba6b0be7ff (patch)
tree63ac3d6fbe5a343b65d538b86ddd7f2566ab348e
parenta0a6d39295a30434b088f4b66439bf5ea21a3e4e (diff)
downloadcpython-git-62bd97303eb6d1fb0109e4a57d38c2ba6b0be7ff.tar.gz
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.)
-rw-r--r--Lib/test/test_code.py9
-rw-r--r--Objects/codeobject.c8
2 files changed, 14 insertions, 3 deletions
diff --git a/Lib/test/test_code.py b/Lib/test/test_code.py
index 2bdd7e7494..9d6b465115 100644
--- a/Lib/test/test_code.py
+++ b/Lib/test/test_code.py
@@ -320,6 +320,15 @@ class CodeTest(unittest.TestCase):
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 3dc9fd787f..ad8f13a781 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 = {