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__()
|
||||
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):
|
||||
def testCompress(self):
|
||||
|
|
|
@ -380,6 +380,10 @@ class CompressorDecompressorTestCase(unittest.TestCase):
|
|||
lzd.__init__()
|
||||
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):
|
||||
|
||||
|
|
|
@ -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."
|
||||
#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 failure, return -1 */
|
||||
static inline Py_ssize_t
|
||||
|
@ -214,12 +237,14 @@ error:
|
|||
|
||||
/*[clinic input]
|
||||
module _bz2
|
||||
class _bz2.BZ2Compressor "BZ2Compressor *" "&BZ2Compressor_Type"
|
||||
class _bz2.BZ2Decompressor "BZ2Decompressor *" "&BZ2Decompressor_Type"
|
||||
class _bz2.BZ2Compressor "BZ2Compressor *" "clinic_state()->bz2_compressor_type"
|
||||
class _bz2.BZ2Decompressor "BZ2Decompressor *" "clinic_state()->bz2_decompressor_type"
|
||||
[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"
|
||||
#undef clinic_state
|
||||
|
||||
/*[clinic input]
|
||||
_bz2.BZ2Compressor.compress
|
||||
|
@ -295,24 +320,43 @@ BZ2_Free(void* ctx, void *ptr)
|
|||
PyMem_RawFree(ptr);
|
||||
}
|
||||
|
||||
/*[clinic input]
|
||||
@classmethod
|
||||
_bz2.BZ2Compressor.__new__
|
||||
|
||||
/* Argument Clinic is not used since the Argument Clinic always want to
|
||||
check the type which would be wrong here */
|
||||
static int
|
||||
_bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel)
|
||||
compresslevel: int = 9
|
||||
Compression level, as a number between 1 and 9.
|
||||
/
|
||||
|
||||
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;
|
||||
BZ2Compressor *self;
|
||||
|
||||
if (!(1 <= compresslevel && compresslevel <= 9)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"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();
|
||||
if (self->lock == NULL) {
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->bzs.opaque = NULL;
|
||||
|
@ -322,49 +366,11 @@ _bz2_BZ2Compressor___init___impl(BZ2Compressor *self, int compresslevel)
|
|||
if (catch_bz2_error(bzerror))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
return (PyObject *)self;
|
||||
|
||||
error:
|
||||
PyThread_free_lock(self->lock);
|
||||
self->lock = 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;
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -395,9 +401,8 @@ static PyMethodDef BZ2Compressor_methods[] = {
|
|||
static PyType_Slot bz2_compressor_type_slots[] = {
|
||||
{Py_tp_dealloc, BZ2Compressor_dealloc},
|
||||
{Py_tp_methods, BZ2Compressor_methods},
|
||||
{Py_tp_init, _bz2_BZ2Compressor___init__},
|
||||
{Py_tp_new, PyType_GenericNew},
|
||||
{Py_tp_doc, (char *)_bz2_BZ2Compressor___init____doc__},
|
||||
{Py_tp_new, _bz2_BZ2Compressor},
|
||||
{Py_tp_doc, (char *)_bz2_BZ2Compressor__doc__},
|
||||
{Py_tp_traverse, BZ2Compressor_traverse},
|
||||
{0, 0}
|
||||
};
|
||||
|
@ -624,28 +629,40 @@ _bz2_BZ2Decompressor_decompress_impl(BZ2Decompressor *self, Py_buffer *data,
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Argument Clinic is not used since the Argument Clinic always want to
|
||||
check the type which would be wrong here */
|
||||
static int
|
||||
_bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self)
|
||||
/*[clinic input]
|
||||
@classmethod
|
||||
_bz2.BZ2Decompressor.__new__
|
||||
|
||||
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;
|
||||
|
||||
PyThread_type_lock lock = PyThread_allocate_lock();
|
||||
if (lock == NULL) {
|
||||
assert(type != NULL && type->tp_alloc != 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");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
if (self->lock != NULL) {
|
||||
PyThread_free_lock(self->lock);
|
||||
}
|
||||
self->lock = lock;
|
||||
|
||||
self->needs_input = 1;
|
||||
self->bzs_avail_in_real = 0;
|
||||
self->input_buffer = NULL;
|
||||
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)
|
||||
goto error;
|
||||
|
||||
|
@ -653,40 +670,13 @@ _bz2_BZ2Decompressor___init___impl(BZ2Decompressor *self)
|
|||
if (catch_bz2_error(bzerror))
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
return (PyObject *)self;
|
||||
|
||||
error:
|
||||
Py_CLEAR(self->unused_data);
|
||||
PyThread_free_lock(self->lock);
|
||||
self->lock = NULL;
|
||||
return -1;
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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
|
||||
BZ2Decompressor_dealloc(BZ2Decompressor *self)
|
||||
{
|
||||
|
@ -738,10 +728,9 @@ static PyMemberDef BZ2Decompressor_members[] = {
|
|||
static PyType_Slot bz2_decompressor_type_slots[] = {
|
||||
{Py_tp_dealloc, BZ2Decompressor_dealloc},
|
||||
{Py_tp_methods, BZ2Decompressor_methods},
|
||||
{Py_tp_init, _bz2_BZ2Decompressor___init__},
|
||||
{Py_tp_doc, (char *)_bz2_BZ2Decompressor___init____doc__},
|
||||
{Py_tp_doc, (char *)_bz2_BZ2Decompressor__doc__},
|
||||
{Py_tp_members, BZ2Decompressor_members},
|
||||
{Py_tp_new, PyType_GenericNew},
|
||||
{Py_tp_new, _bz2_BZ2Decompressor},
|
||||
{Py_tp_traverse, BZ2Decompressor_traverse},
|
||||
{0, 0}
|
||||
};
|
||||
|
@ -762,31 +751,52 @@ static PyType_Spec bz2_decompressor_type_spec = {
|
|||
static int
|
||||
_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);
|
||||
if (bz2_compressor_type == NULL) {
|
||||
if (state->bz2_compressor_type == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int rc = PyModule_AddType(module, bz2_compressor_type);
|
||||
Py_DECREF(bz2_compressor_type);
|
||||
if (rc < 0) {
|
||||
if (PyModule_AddType(module, state->bz2_compressor_type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PyTypeObject *bz2_decompressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
|
||||
state->bz2_decompressor_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
|
||||
&bz2_decompressor_type_spec, NULL);
|
||||
if (bz2_decompressor_type == NULL) {
|
||||
if (state->bz2_decompressor_type == NULL) {
|
||||
return -1;
|
||||
}
|
||||
rc = PyModule_AddType(module, bz2_decompressor_type);
|
||||
Py_DECREF(bz2_decompressor_type);
|
||||
if (rc < 0) {
|
||||
if (PyModule_AddType(module, state->bz2_decompressor_type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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[] = {
|
||||
{Py_mod_exec, _bz2_exec},
|
||||
{0, NULL}
|
||||
|
@ -795,6 +805,10 @@ static struct PyModuleDef_Slot _bz2_slots[] = {
|
|||
static struct PyModuleDef _bz2module = {
|
||||
.m_base = PyModuleDef_HEAD_INIT,
|
||||
.m_name = "_bz2",
|
||||
.m_size = sizeof(_bz2_state),
|
||||
.m_traverse = _bz2_traverse,
|
||||
.m_clear = _bz2_clear,
|
||||
.m_free = _bz2_free,
|
||||
.m_slots = _bz2_slots,
|
||||
};
|
||||
|
||||
|
|
|
@ -734,7 +734,8 @@ Compressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspecs)
|
|||
}
|
||||
|
||||
/*[-clinic input]
|
||||
_lzma.LZMACompressor.__init__
|
||||
@classmethod
|
||||
_lzma.LZMACompressor.__new__
|
||||
|
||||
format: int(c_default="FORMAT_XZ") = FORMAT_XZ
|
||||
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.
|
||||
[-clinic start generated code]*/
|
||||
static int
|
||||
Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
||||
static PyObject *
|
||||
Compressor_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
|
||||
{
|
||||
static char *arg_names[] = {"format", "check", "preset", "filters", NULL};
|
||||
int format = FORMAT_XZ;
|
||||
|
@ -774,31 +775,37 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
|||
uint32_t preset = LZMA_PRESET_DEFAULT;
|
||||
PyObject *preset_obj = 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);
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
|
||||
"|iiOO:LZMACompressor", arg_names,
|
||||
&format, &check, &preset_obj,
|
||||
&filterspecs)) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (format != FORMAT_XZ && check != -1 && check != LZMA_CHECK_NONE) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Integrity checks are only supported by FORMAT_XZ");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (preset_obj != Py_None && filterspecs != Py_None) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Cannot specify both preset and filter chain");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (preset_obj != Py_None) {
|
||||
if (!uint32_converter(preset_obj, &preset)) {
|
||||
return -1;
|
||||
}
|
||||
if (preset_obj != Py_None && !uint32_converter(preset_obj, &preset)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(type != NULL && type->tp_alloc != NULL);
|
||||
self = (Compressor *)type->tp_alloc(type, 0);
|
||||
if (self == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->alloc.opaque = NULL;
|
||||
|
@ -808,8 +815,9 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
|||
|
||||
self->lock = PyThread_allocate_lock();
|
||||
if (self->lock == NULL) {
|
||||
Py_DECREF(self);
|
||||
PyErr_SetString(PyExc_MemoryError, "Unable to allocate lock");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
self->flushed = 0;
|
||||
|
@ -819,31 +827,33 @@ Compressor_init(Compressor *self, PyObject *args, PyObject *kwargs)
|
|||
check = LZMA_CHECK_CRC64;
|
||||
}
|
||||
if (Compressor_init_xz(state, &self->lzs, check, preset, filterspecs) != 0) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case FORMAT_ALONE:
|
||||
if (Compressor_init_alone(state, &self->lzs, preset, filterspecs) != 0) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case FORMAT_RAW:
|
||||
if (Compressor_init_raw(state, &self->lzs, filterspecs) != 0) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Invalid container format: %d", format);
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
|
||||
PyThread_free_lock(self->lock);
|
||||
self->lock = NULL;
|
||||
return -1;
|
||||
return (PyObject *)self;
|
||||
|
||||
error:
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -902,8 +912,7 @@ PyDoc_STRVAR(Compressor_doc,
|
|||
static PyType_Slot lzma_compressor_type_slots[] = {
|
||||
{Py_tp_dealloc, Compressor_dealloc},
|
||||
{Py_tp_methods, Compressor_methods},
|
||||
{Py_tp_init, Compressor_init},
|
||||
{Py_tp_new, PyType_GenericNew},
|
||||
{Py_tp_new, Compressor_new},
|
||||
{Py_tp_doc, (char *)Compressor_doc},
|
||||
{Py_tp_traverse, Compressor_traverse},
|
||||
{0, 0}
|
||||
|
@ -1165,7 +1174,8 @@ Decompressor_init_raw(_lzma_state *state, lzma_stream *lzs, PyObject *filterspec
|
|||
}
|
||||
|
||||
/*[clinic input]
|
||||
_lzma.LZMADecompressor.__init__
|
||||
@classmethod
|
||||
_lzma.LZMADecompressor.__new__
|
||||
|
||||
format: int(c_default="FORMAT_AUTO") = FORMAT_AUTO
|
||||
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.
|
||||
[clinic start generated code]*/
|
||||
|
||||
static int
|
||||
_lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
|
||||
PyObject *memlimit, PyObject *filters)
|
||||
/*[clinic end generated code: output=3e1821f8aa36564c input=81fe684a6c2f8a27]*/
|
||||
static PyObject *
|
||||
_lzma_LZMADecompressor_impl(PyTypeObject *type, int format,
|
||||
PyObject *memlimit, PyObject *filters)
|
||||
/*[clinic end generated code: output=2d46d5e70f10bc7f input=ca40cd1cb1202b0d]*/
|
||||
{
|
||||
Decompressor *self;
|
||||
const uint32_t decoder_flags = LZMA_TELL_ANY_CHECK | LZMA_TELL_NO_CHECK;
|
||||
uint64_t memlimit_ = UINT64_MAX;
|
||||
lzma_ret lzret;
|
||||
_lzma_state *state = PyType_GetModuleState(Py_TYPE(self));
|
||||
_lzma_state *state = PyType_GetModuleState(type);
|
||||
assert(state != NULL);
|
||||
|
||||
if (memlimit != Py_None) {
|
||||
if (format == FORMAT_RAW) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Cannot specify memory limit with FORMAT_RAW");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
memlimit_ = PyLong_AsUnsignedLongLong(memlimit);
|
||||
if (PyErr_Occurred()) {
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (format == FORMAT_RAW && filters == Py_None) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Must specify filters for FORMAT_RAW");
|
||||
return -1;
|
||||
return NULL;
|
||||
} else if (format != FORMAT_RAW && filters != Py_None) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"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.alloc = PyLzma_Malloc;
|
||||
self->alloc.free = PyLzma_Free;
|
||||
self->lzs.allocator = &self->alloc;
|
||||
self->lzs.next_in = NULL;
|
||||
|
||||
PyThread_type_lock lock = PyThread_allocate_lock();
|
||||
if (lock == NULL) {
|
||||
self->lock = PyThread_allocate_lock();
|
||||
if (self->lock == NULL) {
|
||||
Py_DECREF(self);
|
||||
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->needs_input = 1;
|
||||
|
@ -1251,43 +1264,43 @@ _lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
|
|||
case FORMAT_AUTO:
|
||||
lzret = lzma_auto_decoder(&self->lzs, memlimit_, decoder_flags);
|
||||
if (catch_lzma_error(state, lzret)) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case FORMAT_XZ:
|
||||
lzret = lzma_stream_decoder(&self->lzs, memlimit_, decoder_flags);
|
||||
if (catch_lzma_error(state, lzret)) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case FORMAT_ALONE:
|
||||
self->check = LZMA_CHECK_NONE;
|
||||
lzret = lzma_alone_decoder(&self->lzs, memlimit_);
|
||||
if (catch_lzma_error(state, lzret)) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case FORMAT_RAW:
|
||||
self->check = LZMA_CHECK_NONE;
|
||||
if (Decompressor_init_raw(state, &self->lzs, filters) == -1) {
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"Invalid container format: %d", format);
|
||||
break;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return (PyObject *)self;
|
||||
|
||||
error:
|
||||
Py_CLEAR(self->unused_data);
|
||||
PyThread_free_lock(self->lock);
|
||||
self->lock = NULL;
|
||||
return -1;
|
||||
Py_DECREF(self);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1345,9 +1358,8 @@ static PyMemberDef Decompressor_members[] = {
|
|||
static PyType_Slot lzma_decompressor_type_slots[] = {
|
||||
{Py_tp_dealloc, Decompressor_dealloc},
|
||||
{Py_tp_methods, Decompressor_methods},
|
||||
{Py_tp_init, _lzma_LZMADecompressor___init__},
|
||||
{Py_tp_new, PyType_GenericNew},
|
||||
{Py_tp_doc, (char *)_lzma_LZMADecompressor___init____doc__},
|
||||
{Py_tp_new, _lzma_LZMADecompressor},
|
||||
{Py_tp_doc, (char *)_lzma_LZMADecompressor__doc__},
|
||||
{Py_tp_traverse, Decompressor_traverse},
|
||||
{Py_tp_members, Decompressor_members},
|
||||
{0, 0}
|
||||
|
|
|
@ -71,6 +71,48 @@ _bz2_BZ2Compressor_flush(BZ2Compressor *self, PyObject *Py_UNUSED(ignored))
|
|||
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__,
|
||||
"decompress($self, /, data, max_length=-1)\n"
|
||||
"--\n"
|
||||
|
@ -168,4 +210,35 @@ exit:
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(_lzma_LZMADecompressor___init____doc__,
|
||||
PyDoc_STRVAR(_lzma_LZMADecompressor__doc__,
|
||||
"LZMADecompressor(format=FORMAT_AUTO, memlimit=None, filters=None)\n"
|
||||
"--\n"
|
||||
"\n"
|
||||
|
@ -192,14 +192,14 @@ PyDoc_STRVAR(_lzma_LZMADecompressor___init____doc__,
|
|||
"\n"
|
||||
"For one-shot decompression, use the decompress() function instead.");
|
||||
|
||||
static int
|
||||
_lzma_LZMADecompressor___init___impl(Decompressor *self, int format,
|
||||
PyObject *memlimit, PyObject *filters);
|
||||
static PyObject *
|
||||
_lzma_LZMADecompressor_impl(PyTypeObject *type, int format,
|
||||
PyObject *memlimit, PyObject *filters);
|
||||
|
||||
static int
|
||||
_lzma_LZMADecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||
static PyObject *
|
||||
_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)
|
||||
|
||||
#define NUM_KEYWORDS 3
|
||||
|
@ -257,7 +257,7 @@ _lzma_LZMADecompressor___init__(PyObject *self, PyObject *args, PyObject *kwargs
|
|||
}
|
||||
filters = fastargs[2];
|
||||
skip_optional_pos:
|
||||
return_value = _lzma_LZMADecompressor___init___impl((Decompressor *)self, format, memlimit, filters);
|
||||
return_value = _lzma_LZMADecompressor_impl(type, format, memlimit, filters);
|
||||
|
||||
exit:
|
||||
return return_value;
|
||||
|
@ -338,4 +338,4 @@ exit:
|
|||
|
||||
return return_value;
|
||||
}
|
||||
/*[clinic end generated code: output=da3e83ba97244044 input=a9049054013a1b77]*/
|
||||
/*[clinic end generated code: output=96c1fbdada1ef232 input=a9049054013a1b77]*/
|
||||
|
|
Loading…
Reference in New Issue