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:
Zackery Spytz 2023-02-23 06:00:58 -08:00 committed by GitHub
parent 9bba8035bd
commit 665730d217
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 288 additions and 175 deletions

View File

@ -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):

View File

@ -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):

View File

@ -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.

View File

@ -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,
};

View File

@ -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}

View File

@ -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]*/

View File

@ -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]*/