Kaydet (Commit) 12ab296f authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka

Issue #22995: Default implementation of __reduce__ and __reduce_ex__ now

rejects builtin types with not defined __new__.
Added tests for non-pickleable types.
import contextlib import contextlib
import copy
import inspect import inspect
import pickle
import sys import sys
import types import types
import unittest import unittest
...@@ -1318,6 +1320,34 @@ class CoroutineTest(unittest.TestCase): ...@@ -1318,6 +1320,34 @@ class CoroutineTest(unittest.TestCase):
run_async(foo()) run_async(foo())
self.assertEqual(CNT, 0) self.assertEqual(CNT, 0)
def test_copy(self):
async def func(): pass
coro = func()
with self.assertRaises(TypeError):
copy.copy(coro)
aw = coro.__await__()
try:
with self.assertRaises(TypeError):
copy.copy(aw)
finally:
aw.close()
def test_pickle(self):
async def func(): pass
coro = func()
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(coro, proto)
aw = coro.__await__()
try:
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(aw, proto)
finally:
aw.close()
class CoroAsyncIOCompatTest(unittest.TestCase): class CoroAsyncIOCompatTest(unittest.TestCase):
......
import collections import collections
import copy
import pickle
import unittest import unittest
class DictSetTest(unittest.TestCase): class DictSetTest(unittest.TestCase):
...@@ -198,6 +200,22 @@ class DictSetTest(unittest.TestCase): ...@@ -198,6 +200,22 @@ class DictSetTest(unittest.TestCase):
d[42] = d.values() d[42] = d.values()
self.assertRaises(RecursionError, repr, d) self.assertRaises(RecursionError, repr, d)
def test_copy(self):
d = {1: 10, "a": "ABC"}
self.assertRaises(TypeError, copy.copy, d.keys())
self.assertRaises(TypeError, copy.copy, d.values())
self.assertRaises(TypeError, copy.copy, d.items())
def test_pickle(self):
d = {1: 10, "a": "ABC"}
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
self.assertRaises((TypeError, pickle.PicklingError),
pickle.dumps, d.keys(), proto)
self.assertRaises((TypeError, pickle.PicklingError),
pickle.dumps, d.values(), proto)
self.assertRaises((TypeError, pickle.PicklingError),
pickle.dumps, d.items(), proto)
def test_abc_registry(self): def test_abc_registry(self):
d = dict(a=1) d = dict(a=1)
......
import copy
import gc import gc
import pickle
import sys import sys
import unittest import unittest
import warnings import warnings
...@@ -111,6 +113,21 @@ class GeneratorTest(unittest.TestCase): ...@@ -111,6 +113,21 @@ class GeneratorTest(unittest.TestCase):
self.assertEqual(gen.__qualname__, self.assertEqual(gen.__qualname__,
"GeneratorTest.test_name.<locals>.<genexpr>") "GeneratorTest.test_name.<locals>.<genexpr>")
def test_copy(self):
def f():
yield 1
g = f()
with self.assertRaises(TypeError):
copy.copy(g)
def test_pickle(self):
def f():
yield 1
g = f()
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(g, proto)
class ExceptionTest(unittest.TestCase): class ExceptionTest(unittest.TestCase):
# Tests for the issue #23353: check that the currently handled exception # Tests for the issue #23353: check that the currently handled exception
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
# For this purpose, the module-level "ET" symbol is temporarily # For this purpose, the module-level "ET" symbol is temporarily
# monkey-patched when running the "test_xml_etree_c" test suite. # monkey-patched when running the "test_xml_etree_c" test suite.
import copy
import html import html
import io import io
import operator import operator
...@@ -2082,6 +2083,19 @@ class ElementIterTest(unittest.TestCase): ...@@ -2082,6 +2083,19 @@ class ElementIterTest(unittest.TestCase):
self.assertEqual(self._ilist(doc), all_tags) self.assertEqual(self._ilist(doc), all_tags)
self.assertEqual(self._ilist(doc, '*'), all_tags) self.assertEqual(self._ilist(doc, '*'), all_tags)
def test_copy(self):
a = ET.Element('a')
it = a.iter()
with self.assertRaises(TypeError):
copy.copy(it)
def test_pickle(self):
a = ET.Element('a')
it = a.iter()
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(it, proto)
class TreeBuilderTest(unittest.TestCase): class TreeBuilderTest(unittest.TestCase):
sample1 = ('<!DOCTYPE html PUBLIC' sample1 = ('<!DOCTYPE html PUBLIC'
......
import unittest import unittest
from test import support from test import support
import binascii import binascii
import pickle
import random import random
import sys import sys
from test.support import bigmemtest, _1G, _4G from test.support import bigmemtest, _1G, _4G
...@@ -600,6 +601,16 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase): ...@@ -600,6 +601,16 @@ class CompressObjectTestCase(BaseCompressTestCase, unittest.TestCase):
d.flush() d.flush()
self.assertRaises(ValueError, d.copy) self.assertRaises(ValueError, d.copy)
def test_compresspickle(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(zlib.compressobj(zlib.Z_BEST_COMPRESSION), proto)
def test_decompresspickle(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.assertRaises((TypeError, pickle.PicklingError)):
pickle.dumps(zlib.decompressobj(), proto)
# Memory use of the following functions takes into account overallocation # Memory use of the following functions takes into account overallocation
@bigmemtest(size=_1G + 1024 * 1024, memuse=3) @bigmemtest(size=_1G + 1024 * 1024, memuse=3)
......
...@@ -10,6 +10,9 @@ Release date: XXXX-XX-XX ...@@ -10,6 +10,9 @@ Release date: XXXX-XX-XX
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #22995: Default implementation of __reduce__ and __reduce_ex__ now
rejects builtin types with not defined __new__.
- Issue #24802: Avoid buffer overreads when int(), float(), compile(), exec() - Issue #24802: Avoid buffer overreads when int(), float(), compile(), exec()
and eval() are passed bytes-like objects. These objects are not and eval() are passed bytes-like objects. These objects are not
necessarily terminated by a null byte, but the functions assumed they were. necessarily terminated by a null byte, but the functions assumed they were.
......
...@@ -4108,6 +4108,12 @@ reduce_newobj(PyObject *obj) ...@@ -4108,6 +4108,12 @@ reduce_newobj(PyObject *obj)
PyObject *newobj, *newargs, *state, *listitems, *dictitems; PyObject *newobj, *newargs, *state, *listitems, *dictitems;
PyObject *result; PyObject *result;
if (Py_TYPE(obj)->tp_new == NULL) {
PyErr_Format(PyExc_TypeError,
"can't pickle %s objects",
Py_TYPE(obj)->tp_name);
return NULL;
}
if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0) if (_PyObject_GetNewArguments(obj, &args, &kwargs) < 0)
return NULL; return NULL;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment