[Python-checkins] gh-90494: Reject 6th element of the __reduce__() tuple (GH-93609) (GH-93631)

ambv webhook-mailer at python.org
Fri Jun 10 10:00:26 EDT 2022


https://github.com/python/cpython/commit/c3045d809c284a2eb6b54b21ee88b56281cf8378
commit: c3045d809c284a2eb6b54b21ee88b56281cf8378
branch: 3.11
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: ambv <lukasz at langa.pl>
date: 2022-06-10T16:00:19+02:00
summary:

gh-90494: Reject 6th element of the __reduce__() tuple (GH-93609) (GH-93631)

copy.copy() and copy.deepcopy() now always raise a TypeError if
__reduce__() returns a tuple with length 6 instead of silently ignore
the 6th item or produce incorrect result.
(cherry picked from commit a365dd64c2a1f0d142540d5031003f24986f489f)

Co-authored-by: Serhiy Storchaka <storchaka at gmail.com>

files:
A Misc/NEWS.d/next/Library/2022-06-08-20-11-02.gh-issue-90494.LIZT85.rst
M Lib/copy.py
M Lib/pickle.py
M Lib/test/test_copy.py

diff --git a/Lib/copy.py b/Lib/copy.py
index 69bac980be205..1b276afe08121 100644
--- a/Lib/copy.py
+++ b/Lib/copy.py
@@ -258,7 +258,7 @@ def _keep_alive(x, memo):
 
 def _reconstruct(x, memo, func, args,
                  state=None, listiter=None, dictiter=None,
-                 deepcopy=deepcopy):
+                 *, deepcopy=deepcopy):
     deep = memo is not None
     if deep and args:
         args = (deepcopy(arg, memo) for arg in args)
diff --git a/Lib/pickle.py b/Lib/pickle.py
index e7f30f226101f..f027e0432045b 100644
--- a/Lib/pickle.py
+++ b/Lib/pickle.py
@@ -619,7 +619,7 @@ def save_pers(self, pid):
                     "persistent IDs in protocol 0 must be ASCII strings")
 
     def save_reduce(self, func, args, state=None, listitems=None,
-                    dictitems=None, state_setter=None, obj=None):
+                    dictitems=None, state_setter=None, *, obj=None):
         # This API is called by some subclasses
 
         if not isinstance(args, tuple):
diff --git a/Lib/test/test_copy.py b/Lib/test/test_copy.py
index f1ca8cb254d18..f4d91c1686898 100644
--- a/Lib/test/test_copy.py
+++ b/Lib/test/test_copy.py
@@ -678,6 +678,28 @@ def __eq__(self, other):
         self.assertIsNot(x, y)
         self.assertIsNot(x["foo"], y["foo"])
 
+    def test_reduce_6tuple(self):
+        def state_setter(*args, **kwargs):
+            self.fail("shouldn't call this")
+        class C:
+            def __reduce__(self):
+                return C, (), self.__dict__, None, None, state_setter
+        x = C()
+        with self.assertRaises(TypeError):
+            copy.copy(x)
+        with self.assertRaises(TypeError):
+            copy.deepcopy(x)
+
+    def test_reduce_6tuple_none(self):
+        class C:
+            def __reduce__(self):
+                return C, (), self.__dict__, None, None, None
+        x = C()
+        with self.assertRaises(TypeError):
+            copy.copy(x)
+        with self.assertRaises(TypeError):
+            copy.deepcopy(x)
+
     def test_copy_slots(self):
         class C(object):
             __slots__ = ["foo"]
diff --git a/Misc/NEWS.d/next/Library/2022-06-08-20-11-02.gh-issue-90494.LIZT85.rst b/Misc/NEWS.d/next/Library/2022-06-08-20-11-02.gh-issue-90494.LIZT85.rst
new file mode 100644
index 0000000000000..95416768793ea
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-06-08-20-11-02.gh-issue-90494.LIZT85.rst
@@ -0,0 +1,3 @@
+:func:`copy.copy` and :func:`copy.deepcopy` now always raise a TypeError if
+``__reduce__()`` returns a tuple with length 6 instead of silently ignore
+the 6th item or produce incorrect result.



More information about the Python-checkins mailing list