Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e6514f5

Browse files
committed
#19395: Raise exception when pickling a (BZ2|LZMA)(Compressor|Decompressor).
The underlying C libraries provide no mechanism for serializing compressor and decompressor objects, so actually pickling these classes is impractical. Previously, these objects would be pickled without error, but attempting to use a deserialized instance would segfault the interpreter.
2 parents d1b4899 + 3797065 commit e6514f5

4 files changed

Lines changed: 57 additions & 2 deletions

File tree

Lib/test/test_bz2.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import unittest
66
from io import BytesIO
77
import os
8+
import pickle
89
import random
910
import subprocess
1011
import sys
@@ -628,6 +629,11 @@ def testCompress4G(self, size):
628629
finally:
629630
data = None
630631

632+
def testPickle(self):
633+
with self.assertRaises(TypeError):
634+
pickle.dumps(BZ2Compressor())
635+
636+
631637
class BZ2DecompressorTest(BaseTest):
632638
def test_Constructor(self):
633639
self.assertRaises(TypeError, BZ2Decompressor, 42)
@@ -679,6 +685,10 @@ def testDecompress4G(self, size):
679685
compressed = None
680686
decompressed = None
681687

688+
def testPickle(self):
689+
with self.assertRaises(TypeError):
690+
pickle.dumps(BZ2Decompressor())
691+
682692

683693
class CompressDecompressTest(BaseTest):
684694
def testCompress(self):

Lib/test/test_lzma.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from io import BytesIO, UnsupportedOperation
22
import os
3+
import pickle
34
import random
45
import unittest
56

@@ -216,6 +217,14 @@ def test_decompressor_bigmem(self, size):
216217
finally:
217218
input = cdata = ddata = None
218219

220+
# Pickling raises an exception; there's no way to serialize an lzma_stream.
221+
222+
def test_pickle(self):
223+
with self.assertRaises(TypeError):
224+
pickle.dumps(LZMACompressor())
225+
with self.assertRaises(TypeError):
226+
pickle.dumps(LZMADecompressor())
227+
219228

220229
class CompressDecompressFunctionTestCase(unittest.TestCase):
221230

Modules/_bz2module.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,14 @@ BZ2Compressor_flush(BZ2Compressor *self, PyObject *noargs)
248248
return result;
249249
}
250250

251+
static PyObject *
252+
BZ2Compressor_getstate(BZ2Compressor *self, PyObject *noargs)
253+
{
254+
PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object",
255+
Py_TYPE(self)->tp_name);
256+
return NULL;
257+
}
258+
251259
static void*
252260
BZ2_Malloc(void* ctx, int items, int size)
253261
{
@@ -317,10 +325,11 @@ BZ2Compressor_dealloc(BZ2Compressor *self)
317325
}
318326

319327
static PyMethodDef BZ2Compressor_methods[] = {
320-
{"compress", (PyCFunction)BZ2Compressor_compress, METH_VARARGS,
328+
{"compress", (PyCFunction)BZ2Compressor_compress, METH_VARARGS,
321329
BZ2Compressor_compress__doc__},
322-
{"flush", (PyCFunction)BZ2Compressor_flush, METH_NOARGS,
330+
{"flush", (PyCFunction)BZ2Compressor_flush, METH_NOARGS,
323331
BZ2Compressor_flush__doc__},
332+
{"__getstate__", (PyCFunction)BZ2Compressor_getstate, METH_NOARGS},
324333
{NULL}
325334
};
326335

@@ -471,6 +480,14 @@ BZ2Decompressor_decompress(BZ2Decompressor *self, PyObject *args)
471480
return result;
472481
}
473482

483+
static PyObject *
484+
BZ2Decompressor_getstate(BZ2Decompressor *self, PyObject *noargs)
485+
{
486+
PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object",
487+
Py_TYPE(self)->tp_name);
488+
return NULL;
489+
}
490+
474491
static int
475492
BZ2Decompressor_init(BZ2Decompressor *self, PyObject *args, PyObject *kwargs)
476493
{
@@ -521,6 +538,7 @@ BZ2Decompressor_dealloc(BZ2Decompressor *self)
521538
static PyMethodDef BZ2Decompressor_methods[] = {
522539
{"decompress", (PyCFunction)BZ2Decompressor_decompress, METH_VARARGS,
523540
BZ2Decompressor_decompress__doc__},
541+
{"__getstate__", (PyCFunction)BZ2Decompressor_getstate, METH_NOARGS},
524542
{NULL}
525543
};
526544

Modules/_lzmamodule.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,14 @@ Compressor_flush(Compressor *self, PyObject *noargs)
564564
return result;
565565
}
566566

567+
static PyObject *
568+
Compressor_getstate(Compressor *self, PyObject *noargs)
569+
{
570+
PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object",
571+
Py_TYPE(self)->tp_name);
572+
return NULL;
573+
}
574+
567575
static int
568576
Compressor_init_xz(lzma_stream *lzs, int check, uint32_t preset,
569577
PyObject *filterspecs)
@@ -735,6 +743,7 @@ static PyMethodDef Compressor_methods[] = {
735743
Compressor_compress_doc},
736744
{"flush", (PyCFunction)Compressor_flush, METH_NOARGS,
737745
Compressor_flush_doc},
746+
{"__getstate__", (PyCFunction)Compressor_getstate, METH_NOARGS},
738747
{NULL}
739748
};
740749

@@ -892,6 +901,14 @@ Decompressor_decompress(Decompressor *self, PyObject *args)
892901
return result;
893902
}
894903

904+
static PyObject *
905+
Decompressor_getstate(Decompressor *self, PyObject *noargs)
906+
{
907+
PyErr_Format(PyExc_TypeError, "cannot serialize '%s' object",
908+
Py_TYPE(self)->tp_name);
909+
return NULL;
910+
}
911+
895912
static int
896913
Decompressor_init_raw(lzma_stream *lzs, PyObject *filterspecs)
897914
{
@@ -1019,6 +1036,7 @@ Decompressor_dealloc(Decompressor *self)
10191036
static PyMethodDef Decompressor_methods[] = {
10201037
{"decompress", (PyCFunction)Decompressor_decompress, METH_VARARGS,
10211038
Decompressor_decompress_doc},
1039+
{"__getstate__", (PyCFunction)Decompressor_getstate, METH_NOARGS},
10221040
{NULL}
10231041
};
10241042

0 commit comments

Comments
 (0)