mirror of https://github.com/python/cpython
bpo-23224: Fix segfaults and multiple leaks in the lzma and bz2 modules (GH-7822)
lzma.LZMADecompressor and bz2.BZ2Decompressor objects caused segfaults when their `__init__()` methods were not called. lzma.LZMADecompressor, lzma.LZMACompressor, bz2.BZ2Compressor, and bz2.BZ2Decompressor objects would leak locks and internal buffers when their `__init__()` methods were called multiple times. https://bugs.python.org/issue23224
This commit is contained in:
parent
9bba8035bd
commit
665730d217
|
@ -844,6 +844,10 @@ class BZ2DecompressorTest(BaseTest):
|
||||||
bzd.__init__()
|
bzd.__init__()
|
||||||
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
|
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
|
||||||
|
|
||||||
|
def test_uninitialized_BZ2Decompressor_crash(self):
|
||||||
|
self.assertEqual(BZ2Decompressor.__new__(BZ2Decompressor).
|
||||||
|
decompress(bytes()), b'')
|
||||||
|
|
||||||
|
|
||||||
class CompressDecompressTest(BaseTest):
|
class CompressDecompressTest(BaseTest):
|
||||||
def testCompress(self):
|
def testCompress(self):
|
||||||
|
|
|
@ -380,6 +380,10 @@ class CompressorDecompressorTestCase(unittest.TestCase):
|
||||||
lzd.__init__()
|
lzd.__init__()
|
||||||
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
|
self.assertAlmostEqual(gettotalrefcount() - refs_before, 0, delta=10)
|
||||||
|
|
||||||
|
def test_uninitialized_LZMADecompressor_crash(self):
|
||||||
|
self.assertEqual(LZMADecompressor.__new__(LZMADecompressor).
|
||||||
|
decompress(bytes()), b'')
|
||||||
|
|
||||||
|
|
||||||
class CompressDecompressFunctionTestCase(unittest.TestCase):
|
class CompressDecompressFunctionTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
Fix segfaults when creating :class:`lzma.LZMADecompressor` and
|
||||||
|
:class:`bz2.BZ2Decompressor` objects without calling ``__init__()``, and fix
|
||||||
|
leakage of locks and internal buffers when calling the ``__init__()``
|
||||||
|
methods of :class:`lzma.LZMADecompressor`, :class:`lzma.LZMACompressor`,
|
||||||
|
:class:`bz2.BZ2Compressor`, and :class:`bz2.BZ2Decompressor` objects
|
||||||
|
multiple times.
|
|
@ -15,6 +15,29 @@
|
||||||
#error "The maximum block size accepted by libbzip2 is UINT32_MAX."
|
#error "The maximum block size accepted by libbzip2 is UINT32_MAX."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyTypeObject *bz2_compressor_type;
|
||||||
|
PyTypeObject *bz2_decompressor_type;
|
||||||
|
} _bz2_state;
|
||||||
|
|
||||||
|
static inline _bz2_state *
|
||||||
|
get_module_state(PyObject *module)
|
||||||
|
{
|
||||||
|
void *state = PyModule_GetState(module);
|
||||||
|
assert(state != NULL);
|
||||||
|
return (_bz2_state *)state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct PyModuleDef _bz2module;
|
||||||
|
|
||||||
|
static inline _bz2_state *
|
||||||
|
find_module_state_by_def(PyTypeObject *type)
|
||||||
|
{
|
||||||
|
PyObject *module = PyType_GetModuleByDef(type, &_bz2module);
|
||||||
|
assert(module != NULL);
|
||||||
|
return get_module_state(module);
|
||||||
|
}
|
||||||
|
|
||||||
/* On success, return value >= 0
|
/* On success, return value >= 0
|
||||||
On failure, return -1 */
|
On failure, return -1 */
|
||||||
static inline Py_ssize_t
|
static inline Py_ssize_t
|
||||||
|
@ -214,12 +237,14 @@ error:
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
module _bz2
|
module _bz2
|
||||||
class _bz2.BZ2Compressor "BZ2Compressor *" "&BZ2Compressor_Type"
|
class _bz2.BZ2Compressor "BZ2Compressor *" "clinic_state()->bz2_compressor_type"
|
||||||
class _bz2.BZ2Decompressor "BZ2Decompressor *" "&BZ2Decompressor_Type"
|
class _bz2.BZ2Decompressor "BZ2Decompressor *" "clinic_state()->bz2_decompressor_type"
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=dc7d7992a79f9cb7]*/
|
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=92348121632b94c4]*/
|
||||||
|
|
||||||
|
#define clinic_state() (find_module_state_by_def(type))
|
||||||
#include "clinic/_bz2module.c.h"
|
#include "clinic/_bz2module.c.h"
|
||||||
|
#undef clinic_state
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_bz2.BZ2Compressor.compress
|
_bz2.BZ2Compressor.compress
|
||||||
|
@ -295,24 +320,43 @@ BZ2_Free(void* ctx, void *ptr)
|
||||||
PyMem_RawFree(ptr);
|
PyMem_RawFree(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*[clinic input]
|
||||||
|
@classmethod
|
||||||
|
_bz2.BZ2Compressor.__new__
|
||||||
|
|
||||||
/* Argument Clinic is not used since the Argument Clinic always want to
|
compresslevel: int = 9
|
||||||
check the type which would be wrong here */
|
Compression level, as a number between 1 and 9.
|
||||||
static int
|
/
|
||||||
_bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel)
|
|
||||||
|
Create a compressor object for compressing data incrementally.
|
||||||
|
|
||||||
|
For one-shot compression, use the compress() function instead.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_bz2_BZ2Compressor_impl(PyTypeObject *type, int compresslevel)
|
||||||
|
/*[clinic end generated code: output=83346c96beaacad7 input=d4500d2a52c8b263]*/
|
||||||
{
|
{
|
||||||
int bzerror;
|
int bzerror;
|
||||||
|
BZ2Compressor *self;
|
||||||
|
|
||||||
if (!(1 <= compresslevel && compresslevel <= 9)) {
|
if (!(1 <= compresslevel && compresslevel <= 9)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"compresslevel must be between 1 and 9");
|
"compresslevel must be between 1 and 9");
|
||||||
return -1;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(type != NULL && type->tp_alloc != NULL);
|
||||||
|
self = (BZ2Compressor *)type->tp_alloc(type, 0);
|
||||||
|
if (self == NULL) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->lock = PyThread_allocate_lock();
|
self->lock = PyThread_allocate_lock();
|
||||||
if (self->lock == NULL) {
|
if (self->lock == NULL) {
|
||||||
|
Py_DECREF(self);
|
||||||
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->bzs.opaque = NULL;
|
self->bzs.opaque = NULL;
|
||||||
|
@ -322,49 +366,11 @@ _bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel)
|
||||||
if (catch_bz2_error(bzerror))
|
if (catch_bz2_error(bzerror))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return 0;
|
return (PyObject *)self;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
PyThread_free_lock(self->lock);
|
Py_DECREF(self);
|
||||||
self->lock = NULL;
|
return NULL;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_bz2_BZ2Compressor___init____doc__,
|
|
||||||
"BZ2Compressor(compresslevel=9, /)\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Create a compressor object for compressing data incrementally.\n"
|
|
||||||
"\n"
|
|
||||||
" compresslevel\n"
|
|
||||||
" Compression level, as a number between 1 and 9.\n"
|
|
||||||
"\n"
|
|
||||||
"For one-shot compression, use the compress() function instead.");
|
|
||||||
|
|
||||||
static int
|
|
||||||
_bz2_BZ2Compressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
||||||
{
|
|
||||||
int return_value = -1;
|
|
||||||
int compresslevel = 9;
|
|
||||||
|
|
||||||
if (!_PyArg_NoKeywords("BZ2Compressor", kwargs)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (!_PyArg_CheckPositional("BZ2Compressor", PyTuple_GET_SIZE(args), 0, 1)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (PyTuple_GET_SIZE(args) < 1) {
|
|
||||||
goto skip_optional;
|
|
||||||
}
|
|
||||||
compresslevel = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0));
|
|
||||||
if (compresslevel == -1 && PyErr_Occurred()) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
skip_optional:
|
|
||||||
return_value = _bz2_BZ2Compressor___init___impl((BZ2Compressor *)self, compresslevel);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -395,9 +401,8 @@ static PyMethodDef BZ2Compressor_methods[] = {
|
||||||
static PyType_Slot bz2_compressor_type_slots[] = {
|
static PyType_Slot bz2_compressor_type_slots[] = {
|
||||||
{Py_tp_dealloc, BZ2Compressor_dealloc},
|
{Py_tp_dealloc, BZ2Compressor_dealloc},
|
||||||
{Py_tp_methods, BZ2Compressor_methods},
|
{Py_tp_methods, BZ2Compressor_methods},
|
||||||
{Py_tp_init, _bz2_BZ2Compressor___init__},
|
{Py_tp_new, _bz2_BZ2Compressor},
|
||||||
{Py_tp_new, PyType_GenericNew},
|
{Py_tp_doc, (char *)_bz2_BZ2Compressor__doc__},
|
||||||
{Py_tp_doc, (char *)_bz2_BZ2Compressor___init____doc__},
|
|
||||||
{Py_tp_traverse, BZ2Compressor_traverse},
|
{Py_tp_traverse, BZ2Compressor_traverse},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
@ -624,28 +629,40 @@ _bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Argument Clinic is not used since the Argument Clinic always want to
|
/*[clinic input]
|
||||||
check the type which would be wrong here */
|
@classmethod
|
||||||
static int
|
_bz2.BZ2Decompressor.__new__
|
||||||
_bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self)
|
|
||||||
|
Create a decompressor object for decompressing data incrementally.
|
||||||
|
|
||||||
|
For one-shot decompression, use the decompress() function instead.
|
||||||
|
[clinic start generated code]*/
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_bz2_BZ2Decompressor_impl(PyTypeObject *type)
|
||||||
|
/*[clinic end generated code: output=5150d51ccaab220e input=b87413ce51853528]*/
|
||||||
{
|
{
|
||||||
|
BZ2Decompressor *self;
|
||||||
int bzerror;
|
int bzerror;
|
||||||
|
|
||||||
PyThread_type_lock lock = PyThread_allocate_lock();
|
assert(type != NULL && type->tp_alloc != NULL);
|
||||||
if (lock == NULL) {
|
self = (BZ2Decompressor *)type->tp_alloc(type, 0);
|
||||||
|
if (self == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
self->lock = PyThread_allocate_lock();
|
||||||
|
if (self->lock == NULL) {
|
||||||
|
Py_DECREF(self);
|
||||||
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (self->lock != NULL) {
|
|
||||||
PyThread_free_lock(self->lock);
|
|
||||||
}
|
|
||||||
self->lock = lock;
|
|
||||||
|
|
||||||
self->needs_input = 1;
|
self->needs_input = 1;
|
||||||
self->bzs_avail_in_real = 0;
|
self->bzs_avail_in_real = 0;
|
||||||
self->input_buffer = NULL;
|
self->input_buffer = NULL;
|
||||||
self->input_buffer_size = 0;
|
self->input_buffer_size = 0;
|
||||||
Py_XSETREF(self->unused_data, PyBytes_FromStringAndSize(NULL, 0));
|
self->unused_data = PyBytes_FromStringAndSize(NULL, 0);
|
||||||
if (self->unused_data == NULL)
|
if (self->unused_data == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
@ -653,40 +670,13 @@ _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self)
|
||||||
if (catch_bz2_error(bzerror))
|
if (catch_bz2_error(bzerror))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
return 0;
|
return (PyObject *)self;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Py_CLEAR(self->unused_data);
|
Py_DECREF(self);
|
||||||
PyThread_free_lock(self->lock);
|
return NULL;
|
||||||
self->lock = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
_bz2_BZ2Decompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
|
||||||
{
|
|
||||||
int return_value = -1;
|
|
||||||
|
|
||||||
if (!_PyArg_NoPositional("BZ2Decompressor", args)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (!_PyArg_NoKeywords("BZ2Decompressor", kwargs)) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
return_value = _bz2_BZ2Decompressor___init___impl((BZ2Decompressor *)self);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return return_value;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(_bz2_BZ2Decompressor___init____doc__,
|
|
||||||
"BZ2Decompressor()\n"
|
|
||||||
"--\n"
|
|
||||||
"\n"
|
|
||||||
"Create a decompressor object for decompressing data incrementally.\n"
|
|
||||||
"\n"
|
|
||||||
"For one-shot decompression, use the decompress() function instead.");
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
BZ2Decompressor_dealloc(BZ2Decompressor *self)
|
BZ2Decompressor_dealloc(BZ2Decompressor *self)
|
||||||
{
|
{
|
||||||
|
@ -738,10 +728,9 @@ static PyMemberDef BZ2Decompressor_members[] = {
|
||||||
static PyType_Slot bz2_decompressor_type_slots[] = {
|
static PyType_Slot bz2_decompressor_type_slots[] = {
|
||||||
{Py_tp_dealloc, BZ2Decompressor_dealloc},
|
{Py_tp_dealloc, BZ2Decompressor_dealloc},
|
||||||
{Py_tp_methods, BZ2Decompressor_methods},
|
{Py_tp_methods, BZ2Decompressor_methods},
|
||||||
{Py_tp_init, _bz2_BZ2Decompressor___init__},
|
{Py_tp_doc, (char *)_bz2_BZ2Decompressor__doc__},
|
||||||
{Py_tp_doc, (char *)_bz2_BZ2Decompressor___init____doc__},
|
|
||||||
{Py_tp_members, BZ2Decompressor_members},
|
{Py_tp_members, BZ2Decompressor_members},
|
||||||
{Py_tp_new, PyType_GenericNew},
|
{Py_tp_new, _bz2_BZ2Decompressor},
|
||||||
{Py_tp_traverse, BZ2Decompressor_traverse},
|
{Py_tp_traverse, BZ2Decompressor_traverse},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
};
|
};
|
||||||
|
@ -762,31 +751,52 @@ static PyType_Spec bz2_decompressor_type_spec = {
|
||||||
static int
|
static int
|
||||||
_bz2_exec(PyObject *module)
|
_bz2_exec(PyObject *module)
|
||||||
{
|
{
|
||||||
PyTypeObject *bz2_compressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
|
_bz2_state *state = get_module_state(module);
|
||||||
|
state->bz2_compressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
|
||||||
&bz2_compressor_type_spec, NULL);
|
&bz2_compressor_type_spec, NULL);
|
||||||
if (bz2_compressor_type == NULL) {
|
if (state->bz2_compressor_type == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int rc = PyModule_AddType(module, bz2_compressor_type);
|
if (PyModule_AddType(module, state->bz2_compressor_type) < 0) {
|
||||||
Py_DECREF(bz2_compressor_type);
|
|
||||||
if (rc < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyTypeObject *bz2_decompressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
|
state->bz2_decompressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
|
||||||
&bz2_decompressor_type_spec, NULL);
|
&bz2_decompressor_type_spec, NULL);
|
||||||
if (bz2_decompressor_type == NULL) {
|
if (state->bz2_decompressor_type == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
rc = PyModule_AddType(module, bz2_decompressor_type);
|
if (PyModule_AddType(module, state->bz2_decompressor_type) < 0) {
|
||||||
Py_DECREF(bz2_decompressor_type);
|
|
||||||
if (rc < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_bz2_traverse(PyObject *module, visitproc visit, void *arg)
|
||||||
|
{
|
||||||
|
_bz2_state *state = get_module_state(module);
|
||||||
|
Py_VISIT(state->bz2_compressor_type);
|
||||||
|
Py_VISIT(state->bz2_decompressor_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_bz2_clear(PyObject *module)
|
||||||
|
{
|
||||||
|
_bz2_state *state = get_module_state(module);
|
||||||
|
Py_CLEAR(state->bz2_compressor_type);
|
||||||
|
Py_CLEAR(state->bz2_decompressor_type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_bz2_free(void *module)
|
||||||
|
{
|
||||||
|
(void)_bz2_clear((PyObject *)module);
|
||||||
|
}
|
||||||
|
|
||||||
static struct PyModuleDef_Slot _bz2_slots[] = {
|
static struct PyModuleDef_Slot _bz2_slots[] = {
|
||||||
{Py_mod_exec, _bz2_exec},
|
{Py_mod_exec, _bz2_exec},
|
||||||
{0, NULL}
|
{0, NULL}
|
||||||
|
@ -795,6 +805,10 @@ static struct PyModuleDef_Slot _bz2_slots[] = {
|
||||||
static struct PyModuleDef _bz2module = {
|
static struct PyModuleDef _bz2module = {
|
||||||
.m_base = PyModuleDef_HEAD_INIT,
|
.m_base = PyModuleDef_HEAD_INIT,
|
||||||
.m_name = "_bz2",
|
.m_name = "_bz2",
|
||||||
|
.m_size = sizeof(_bz2_state),
|
||||||
|
.m_traverse = _bz2_traverse,
|
||||||
|
.m_clear = _bz2_clear,
|
||||||
|
.m_free = _bz2_free,
|
||||||
.m_slots = _bz2_slots,
|
.m_slots = _bz2_slots,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -734,7 +734,8 @@ Compressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspecs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[-clinic input]
|
/*[-clinic input]
|
||||||
_lzma.LZMACompressor.__init__
|
@classmethod
|
||||||
|
_lzma.LZMACompressor.__new__
|
||||||
|
|
||||||
format: int(c_default="FORMAT_XZ") = FORMAT_XZ
|
format: int(c_default="FORMAT_XZ") = FORMAT_XZ
|
||||||
The container format to use for the output. This can
|
The container format to use for the output. This can
|
||||||
|
@ -765,8 +766,8 @@ the raw compressor does not support preset compression levels.
|
||||||
|
|
||||||
For one-shot compression, use the compress() function instead.
|
For one-shot compression, use the compress() function instead.
|
||||||
[-clinic start generated code]*/
|
[-clinic start generated code]*/
|
||||||
static int
|
static PyObject *
|
||||||
Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
Compressor_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
static char *arg_names[] = {"format", "check", "preset", "filters", NULL};
|
static char *arg_names[] = {"format", "check", "preset", "filters", NULL};
|
||||||
int format = FORMAT_XZ;
|
int format = FORMAT_XZ;
|
||||||
|
@ -774,31 +775,37 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
||||||
uint32_t preset = LZMA_PRESET_DEFAULT;
|
uint32_t preset = LZMA_PRESET_DEFAULT;
|
||||||
PyObject *preset_obj = Py_None;
|
PyObject *preset_obj = Py_None;
|
||||||
PyObject *filterspecs = Py_None;
|
PyObject *filterspecs = Py_None;
|
||||||
_lzma_state *state = PyType_GetModuleState(Py_TYPE(self));
|
Compressor *self;
|
||||||
|
|
||||||
|
_lzma_state *state = PyType_GetModuleState(type);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||||
"|iiOO:LZMACompressor", arg_names,
|
"|iiOO:LZMACompressor", arg_names,
|
||||||
&format, &check, &preset_obj,
|
&format, &check, &preset_obj,
|
||||||
&filterspecs)) {
|
&filterspecs)) {
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format != FORMAT_XZ && check != -1 && check != LZMA_CHECK_NONE) {
|
if (format != FORMAT_XZ && check != -1 && check != LZMA_CHECK_NONE) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Integrity checks are only supported by FORMAT_XZ");
|
"Integrity checks are only supported by FORMAT_XZ");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preset_obj != Py_None && filterspecs != Py_None) {
|
if (preset_obj != Py_None && filterspecs != Py_None) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Cannot specify both preset and filter chain");
|
"Cannot specify both preset and filter chain");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preset_obj != Py_None) {
|
if (preset_obj != Py_None && !uint32_converter(preset_obj, &preset)) {
|
||||||
if (!uint32_converter(preset_obj, &preset)) {
|
return NULL;
|
||||||
return -1;
|
}
|
||||||
}
|
|
||||||
|
assert(type != NULL && type->tp_alloc != NULL);
|
||||||
|
self = (Compressor *)type->tp_alloc(type, 0);
|
||||||
|
if (self == NULL) {
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->alloc.opaque = NULL;
|
self->alloc.opaque = NULL;
|
||||||
|
@ -808,8 +815,9 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
||||||
|
|
||||||
self->lock = PyThread_allocate_lock();
|
self->lock = PyThread_allocate_lock();
|
||||||
if (self->lock == NULL) {
|
if (self->lock == NULL) {
|
||||||
|
Py_DECREF(self);
|
||||||
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->flushed = 0;
|
self->flushed = 0;
|
||||||
|
@ -819,31 +827,33 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
||||||
check = LZMA_CHECK_CRC64;
|
check = LZMA_CHECK_CRC64;
|
||||||
}
|
}
|
||||||
if (Compressor_init_xz(state, &self->lzs, check, preset, filterspecs) != 0) {
|
if (Compressor_init_xz(state, &self->lzs, check, preset, filterspecs) != 0) {
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
case FORMAT_ALONE:
|
case FORMAT_ALONE:
|
||||||
if (Compressor_init_alone(state, &self->lzs, preset, filterspecs) != 0) {
|
if (Compressor_init_alone(state, &self->lzs, preset, filterspecs) != 0) {
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
case FORMAT_RAW:
|
case FORMAT_RAW:
|
||||||
if (Compressor_init_raw(state, &self->lzs, filterspecs) != 0) {
|
if (Compressor_init_raw(state, &self->lzs, filterspecs) != 0) {
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"Invalid container format: %d", format);
|
"Invalid container format: %d", format);
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyThread_free_lock(self->lock);
|
return (PyObject *)self;
|
||||||
self->lock = NULL;
|
|
||||||
return -1;
|
error:
|
||||||
|
Py_DECREF(self);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -902,8 +912,7 @@ PyDoc_STRVAR(Compressor_doc,
|
||||||
static PyType_Slot lzma_compressor_type_slots[] = {
|
static PyType_Slot lzma_compressor_type_slots[] = {
|
||||||
{Py_tp_dealloc, Compressor_dealloc},
|
{Py_tp_dealloc, Compressor_dealloc},
|
||||||
{Py_tp_methods, Compressor_methods},
|
{Py_tp_methods, Compressor_methods},
|
||||||
{Py_tp_init, Compressor_init},
|
{Py_tp_new, Compressor_new},
|
||||||
{Py_tp_new, PyType_GenericNew},
|
|
||||||
{Py_tp_doc, (char *)Compressor_doc},
|
{Py_tp_doc, (char *)Compressor_doc},
|
||||||
{Py_tp_traverse, Compressor_traverse},
|
{Py_tp_traverse, Compressor_traverse},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
|
@ -1165,7 +1174,8 @@ Decompressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspec
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
_lzma.LZMADecompressor.__init__
|
@classmethod
|
||||||
|
_lzma.LZMADecompressor.__new__
|
||||||
|
|
||||||
format: int(c_default="FORMAT_AUTO") = FORMAT_AUTO
|
format: int(c_default="FORMAT_AUTO") = FORMAT_AUTO
|
||||||
Specifies the container format of the input stream. If this is
|
Specifies the container format of the input stream. If this is
|
||||||
|
@ -1189,54 +1199,57 @@ Create a decompressor object for decompressing data incrementally.
|
||||||
For one-shot decompression, use the decompress() function instead.
|
For one-shot decompression, use the decompress() function instead.
|
||||||
[clinic start generated code]*/
|
[clinic start generated code]*/
|
||||||
|
|
||||||
static int
|
static PyObject *
|
||||||
_lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
|
_lzma_LZMADecompressor_impl(PyTypeObject *type, int format,
|
||||||
PyObject *memlimit, PyObject *filters)
|
PyObject *memlimit, PyObject *filters)
|
||||||
/*[clinic end generated code: output=3e1821f8aa36564c input=81fe684a6c2f8a27]*/
|
/*[clinic end generated code: output=2d46d5e70f10bc7f input=ca40cd1cb1202b0d]*/
|
||||||
{
|
{
|
||||||
|
Decompressor *self;
|
||||||
const uint32_t decoder_flags = LZMA_TELL_ANY_CHECK | LZMA_TELL_NO_CHECK;
|
const uint32_t decoder_flags = LZMA_TELL_ANY_CHECK | LZMA_TELL_NO_CHECK;
|
||||||
uint64_t memlimit_ = UINT64_MAX;
|
uint64_t memlimit_ = UINT64_MAX;
|
||||||
lzma_ret lzret;
|
lzma_ret lzret;
|
||||||
_lzma_state *state = PyType_GetModuleState(Py_TYPE(self));
|
_lzma_state *state = PyType_GetModuleState(type);
|
||||||
assert(state != NULL);
|
assert(state != NULL);
|
||||||
|
|
||||||
if (memlimit != Py_None) {
|
if (memlimit != Py_None) {
|
||||||
if (format == FORMAT_RAW) {
|
if (format == FORMAT_RAW) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Cannot specify memory limit with FORMAT_RAW");
|
"Cannot specify memory limit with FORMAT_RAW");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
memlimit_ = PyLong_AsUnsignedLongLong(memlimit);
|
memlimit_ = PyLong_AsUnsignedLongLong(memlimit);
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (format == FORMAT_RAW && filters == Py_None) {
|
if (format == FORMAT_RAW && filters == Py_None) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Must specify filters for FORMAT_RAW");
|
"Must specify filters for FORMAT_RAW");
|
||||||
return -1;
|
return NULL;
|
||||||
} else if (format != FORMAT_RAW && filters != Py_None) {
|
} else if (format != FORMAT_RAW && filters != Py_None) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"Cannot specify filters except with FORMAT_RAW");
|
"Cannot specify filters except with FORMAT_RAW");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(type != NULL && type->tp_alloc != NULL);
|
||||||
|
self = (Decompressor *)type->tp_alloc(type, 0);
|
||||||
|
if (self == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
self->alloc.opaque = NULL;
|
self->alloc.opaque = NULL;
|
||||||
self->alloc.alloc = PyLzma_Malloc;
|
self->alloc.alloc = PyLzma_Malloc;
|
||||||
self->alloc.free = PyLzma_Free;
|
self->alloc.free = PyLzma_Free;
|
||||||
self->lzs.allocator = &self->alloc;
|
self->lzs.allocator = &self->alloc;
|
||||||
self->lzs.next_in = NULL;
|
self->lzs.next_in = NULL;
|
||||||
|
|
||||||
PyThread_type_lock lock = PyThread_allocate_lock();
|
self->lock = PyThread_allocate_lock();
|
||||||
if (lock == NULL) {
|
if (self->lock == NULL) {
|
||||||
|
Py_DECREF(self);
|
||||||
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (self->lock != NULL) {
|
|
||||||
PyThread_free_lock(self->lock);
|
|
||||||
}
|
|
||||||
self->lock = lock;
|
|
||||||
|
|
||||||
self->check = LZMA_CHECK_UNKNOWN;
|
self->check = LZMA_CHECK_UNKNOWN;
|
||||||
self->needs_input = 1;
|
self->needs_input = 1;
|
||||||
|
@ -1251,43 +1264,43 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
|
||||||
case FORMAT_AUTO:
|
case FORMAT_AUTO:
|
||||||
lzret = lzma_auto_decoder(&self->lzs, memlimit_, decoder_flags);
|
lzret = lzma_auto_decoder(&self->lzs, memlimit_, decoder_flags);
|
||||||
if (catch_lzma_error(state, lzret)) {
|
if (catch_lzma_error(state, lzret)) {
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
case FORMAT_XZ:
|
case FORMAT_XZ:
|
||||||
lzret = lzma_stream_decoder(&self->lzs, memlimit_, decoder_flags);
|
lzret = lzma_stream_decoder(&self->lzs, memlimit_, decoder_flags);
|
||||||
if (catch_lzma_error(state, lzret)) {
|
if (catch_lzma_error(state, lzret)) {
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
case FORMAT_ALONE:
|
case FORMAT_ALONE:
|
||||||
self->check = LZMA_CHECK_NONE;
|
self->check = LZMA_CHECK_NONE;
|
||||||
lzret = lzma_alone_decoder(&self->lzs, memlimit_);
|
lzret = lzma_alone_decoder(&self->lzs, memlimit_);
|
||||||
if (catch_lzma_error(state, lzret)) {
|
if (catch_lzma_error(state, lzret)) {
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
case FORMAT_RAW:
|
case FORMAT_RAW:
|
||||||
self->check = LZMA_CHECK_NONE;
|
self->check = LZMA_CHECK_NONE;
|
||||||
if (Decompressor_init_raw(state, &self->lzs, filters) == -1) {
|
if (Decompressor_init_raw(state, &self->lzs, filters) == -1) {
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"Invalid container format: %d", format);
|
"Invalid container format: %d", format);
|
||||||
break;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return (PyObject *)self;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
Py_CLEAR(self->unused_data);
|
Py_DECREF(self);
|
||||||
PyThread_free_lock(self->lock);
|
return NULL;
|
||||||
self->lock = NULL;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1345,9 +1358,8 @@ static PyMemberDef Decompressor_members[] = {
|
||||||
static PyType_Slot lzma_decompressor_type_slots[] = {
|
static PyType_Slot lzma_decompressor_type_slots[] = {
|
||||||
{Py_tp_dealloc, Decompressor_dealloc},
|
{Py_tp_dealloc, Decompressor_dealloc},
|
||||||
{Py_tp_methods, Decompressor_methods},
|
{Py_tp_methods, Decompressor_methods},
|
||||||
{Py_tp_init, _lzma_LZMADecompressor___init__},
|
{Py_tp_new, _lzma_LZMADecompressor},
|
||||||
{Py_tp_new, PyType_GenericNew},
|
{Py_tp_doc, (char *)_lzma_LZMADecompressor__doc__},
|
||||||
{Py_tp_doc, (char *)_lzma_LZMADecompressor___init____doc__},
|
|
||||||
{Py_tp_traverse, Decompressor_traverse},
|
{Py_tp_traverse, Decompressor_traverse},
|
||||||
{Py_tp_members, Decompressor_members},
|
{Py_tp_members, Decompressor_members},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
|
|
|
@ -71,6 +71,48 @@ _bz2_BZ2Compressor_flush(BZ2Compressor *self, PyObject *Py_UNUSED(ignored))
|
||||||
return _bz2_BZ2Compressor_flush_impl(self);
|
return _bz2_BZ2Compressor_flush_impl(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(_bz2_BZ2Compressor__doc__,
|
||||||
|
"BZ2Compressor(compresslevel=9, /)\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Create a compressor object for compressing data incrementally.\n"
|
||||||
|
"\n"
|
||||||
|
" compresslevel\n"
|
||||||
|
" Compression level, as a number between 1 and 9.\n"
|
||||||
|
"\n"
|
||||||
|
"For one-shot compression, use the compress() function instead.");
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_bz2_BZ2Compressor_impl(PyTypeObject *type, int compresslevel);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_bz2_BZ2Compressor(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyTypeObject *base_tp = clinic_state()->bz2_compressor_type;
|
||||||
|
int compresslevel = 9;
|
||||||
|
|
||||||
|
if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
|
||||||
|
!_PyArg_NoKeywords("BZ2Compressor", kwargs)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!_PyArg_CheckPositional("BZ2Compressor", PyTuple_GET_SIZE(args), 0, 1)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (PyTuple_GET_SIZE(args) < 1) {
|
||||||
|
goto skip_optional;
|
||||||
|
}
|
||||||
|
compresslevel = _PyLong_AsInt(PyTuple_GET_ITEM(args, 0));
|
||||||
|
if (compresslevel == -1 && PyErr_Occurred()) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
skip_optional:
|
||||||
|
return_value = _bz2_BZ2Compressor_impl(type, compresslevel);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(_bz2_BZ2Decompressor_decompress__doc__,
|
PyDoc_STRVAR(_bz2_BZ2Decompressor_decompress__doc__,
|
||||||
"decompress($self, /, data, max_length=-1)\n"
|
"decompress($self, /, data, max_length=-1)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
|
@ -168,4 +210,35 @@ exit:
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=829bed4097cf2e63 input=a9049054013a1b77]*/
|
|
||||||
|
PyDoc_STRVAR(_bz2_BZ2Decompressor__doc__,
|
||||||
|
"BZ2Decompressor()\n"
|
||||||
|
"--\n"
|
||||||
|
"\n"
|
||||||
|
"Create a decompressor object for decompressing data incrementally.\n"
|
||||||
|
"\n"
|
||||||
|
"For one-shot decompression, use the decompress() function instead.");
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_bz2_BZ2Decompressor_impl(PyTypeObject *type);
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_bz2_BZ2Decompressor(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||||
|
{
|
||||||
|
PyObject *return_value = NULL;
|
||||||
|
PyTypeObject *base_tp = clinic_state()->bz2_decompressor_type;
|
||||||
|
|
||||||
|
if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
|
||||||
|
!_PyArg_NoPositional("BZ2Decompressor", args)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if ((type == base_tp || type->tp_init == base_tp->tp_init) &&
|
||||||
|
!_PyArg_NoKeywords("BZ2Decompressor", kwargs)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
return_value = _bz2_BZ2Decompressor_impl(type);
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
/*[clinic end generated code: output=805400e4805098ec input=a9049054013a1b77]*/
|
||||||
|
|
|
@ -169,7 +169,7 @@ exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(_lzma_LZMADecompressor___init____doc__,
|
PyDoc_STRVAR(_lzma_LZMADecompressor__doc__,
|
||||||
"LZMADecompressor(format=FORMAT_AUTO, memlimit=None, filters=None)\n"
|
"LZMADecompressor(format=FORMAT_AUTO, memlimit=None, filters=None)\n"
|
||||||
"--\n"
|
"--\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -192,14 +192,14 @@ PyDoc_STRVAR(_lzma_LZMADecompressor___init____doc__,
|
||||||
"\n"
|
"\n"
|
||||||
"For one-shot decompression, use the decompress() function instead.");
|
"For one-shot decompression, use the decompress() function instead.");
|
||||||
|
|
||||||
static int
|
static PyObject *
|
||||||
_lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
|
_lzma_LZMADecompressor_impl(PyTypeObject *type, int format,
|
||||||
PyObject *memlimit, PyObject *filters);
|
PyObject *memlimit, PyObject *filters);
|
||||||
|
|
||||||
static int
|
static PyObject *
|
||||||
_lzma_LZMADecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
_lzma_LZMADecompressor(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||||
{
|
{
|
||||||
int return_value = -1;
|
PyObject *return_value = NULL;
|
||||||
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
#if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
|
||||||
|
|
||||||
#define NUM_KEYWORDS 3
|
#define NUM_KEYWORDS 3
|
||||||
|
@ -257,7 +257,7 @@ _lzma_LZMADecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs
|
||||||
}
|
}
|
||||||
filters = fastargs[2];
|
filters = fastargs[2];
|
||||||
skip_optional_pos:
|
skip_optional_pos:
|
||||||
return_value = _lzma_LZMADecompressor___init___impl((Decompressor *)self, format, memlimit, filters);
|
return_value = _lzma_LZMADecompressor_impl(type, format, memlimit, filters);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return return_value;
|
return return_value;
|
||||||
|
@ -338,4 +338,4 @@ exit:
|
||||||
|
|
||||||
return return_value;
|
return return_value;
|
||||||
}
|
}
|
||||||
/*[clinic end generated code: output=da3e83ba97244044 input=a9049054013a1b77]*/
|
/*[clinic end generated code: output=96c1fbdada1ef232 input=a9049054013a1b77]*/
|
||||||
|
|
Loading…
Reference in New Issue