static void pylzma_decomp_dealloc(CCompatDecompressionObject *self) { free_lzma_stream(&self->stream); FREE_AND_NULL(self->unconsumed_tail); DEC_AND_NULL(self->unused_data); PyObject_Del(self); }
static void pylzma_compfile_dealloc(CCompressionFileObject *self) { DEC_AND_NULL(self->inFile); LzmaEnc_Destroy(self->encoder, &allocator, &allocator); if (self->outStream.data != NULL) { free(self->outStream.data); } self->ob_type->tp_free((PyObject*)self); }
static PyObject *pylzma_decomp_decompress(CDecompressionObject *self, PyObject *args) { PyObject *result=NULL; unsigned char *data, *next_in, *next_out; int length, start_total_out, res, max_length=BLOCK_SIZE; SizeT avail_in, avail_out; unsigned char properties[LZMA_PROPERTIES_SIZE]; SizeT inProcessed, outProcessed; if (!PyArg_ParseTuple(args, "s#|l", &data, &length, &max_length)) return NULL; if (max_length <= 0) { PyErr_SetString(PyExc_ValueError, "bufsize must be greater than zero"); return NULL; } start_total_out = self->total_out; if (self->unconsumed_length > 0) { self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, self->unconsumed_length + length); next_in = (unsigned char *)self->unconsumed_tail; memcpy(next_in + self->unconsumed_length, data, length); } else next_in = data; avail_in = self->unconsumed_length + length; if (self->need_properties && avail_in < sizeof(properties)) { // we need enough bytes to read the properties if (!self->unconsumed_length) { self->unconsumed_tail = (unsigned char *)malloc(length); memcpy(self->unconsumed_tail, data, length); } self->unconsumed_length += length; return PyString_FromString(""); } if (self->need_properties) { self->need_properties = 0; memcpy(&properties, next_in, sizeof(properties)); avail_in -= sizeof(properties); next_in += sizeof(properties); if (self->unconsumed_length >= sizeof(properties)-length) { self->unconsumed_length -= sizeof(properties)-length; if (self->unconsumed_length > 0) { memcpy(self->unconsumed_tail, self->unconsumed_tail+sizeof(properties), self->unconsumed_length); self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, self->unconsumed_length); } else FREE_AND_NULL(self->unconsumed_tail); } if (LzmaDecodeProperties(&self->state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) { PyErr_SetString(PyExc_TypeError, "Incorrect stream properties"); goto exit; } self->state.Probs = (CProb *)malloc(LzmaGetNumProbs(&self->state.Properties) * sizeof(CProb)); if (self->state.Probs == 0) { PyErr_NoMemory(); goto exit; } if (self->state.Properties.DictionarySize == 0) self->state.Dictionary = 0; else { self->state.Dictionary = (unsigned char *)malloc(self->state.Properties.DictionarySize); if (self->state.Dictionary == 0) { free(self->state.Probs); self->state.Probs = NULL; PyErr_NoMemory(); goto exit; } } LzmaDecoderInit(&self->state); } if (avail_in == 0) // no more bytes to decompress return PyString_FromString(""); if (!(result = PyString_FromStringAndSize(NULL, max_length))) return NULL; next_out = (unsigned char *)PyString_AS_STRING(result); avail_out = max_length; Py_BEGIN_ALLOW_THREADS // Decompress until EOS marker is reached res = LzmaDecode(&self->state, next_in, avail_in, &inProcessed, next_out, avail_out, &outProcessed, 0); Py_END_ALLOW_THREADS self->total_out += outProcessed; next_in += inProcessed; avail_in -= inProcessed; next_out += outProcessed; avail_out -= outProcessed; if (res != LZMA_RESULT_OK) { PyErr_SetString(PyExc_ValueError, "data error during decompression"); DEC_AND_NULL(result); goto exit; } /* Not all of the compressed data could be accomodated in the output buffer of specified size. Return the unconsumed tail in an attribute.*/ if (avail_in > 0) { if (avail_in != self->unconsumed_length) { if (avail_in > self->unconsumed_length) { self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, avail_in); memcpy(self->unconsumed_tail, next_in, avail_in); } if (avail_in < self->unconsumed_length) { memcpy(self->unconsumed_tail, next_in, avail_in); self->unconsumed_tail = (unsigned char *)realloc(self->unconsumed_tail, avail_in); } } if (!self->unconsumed_tail) { PyErr_NoMemory(); DEC_AND_NULL(result); goto exit; } } else FREE_AND_NULL(self->unconsumed_tail); self->unconsumed_length = avail_in; _PyString_Resize(&result, self->total_out - start_total_out); exit: return result; }
static PyObject *pylzma_decomp_flush(CDecompressionObject *self, PyObject *args) { PyObject *result=NULL; int res; SizeT avail_out, outsize; unsigned char *tmp; SizeT inProcessed, outProcessed; if (!PyArg_ParseTuple(args, "")) return NULL; if (self->max_length != -1) avail_out = self->max_length - self->total_out; else avail_out = BLOCK_SIZE; if (avail_out == 0) // no more remaining data return PyString_FromString(""); result = PyString_FromStringAndSize(NULL, avail_out); if (result == NULL) return NULL; tmp = (unsigned char *)PyString_AS_STRING(result); outsize = 0; while (1) { Py_BEGIN_ALLOW_THREADS if (self->unconsumed_length == 0) // No remaining data res = LzmaDecode(&self->state, (unsigned char *)"", 0, &inProcessed, tmp, avail_out, &outProcessed, 1); else { // Decompress remaining data res = LzmaDecode(&self->state, self->unconsumed_tail, self->unconsumed_length, &inProcessed, tmp, avail_out, &outProcessed, 1); self->unconsumed_length -= inProcessed; if (self->unconsumed_length > 0) memcpy(self->unconsumed_tail, self->unconsumed_tail + inProcessed, self->unconsumed_length); else FREE_AND_NULL(self->unconsumed_tail); } Py_END_ALLOW_THREADS if (res != LZMA_RESULT_OK) { PyErr_SetString(PyExc_ValueError, "data error during decompression"); DEC_AND_NULL(result); goto exit; } self->total_out += outProcessed; outsize += outProcessed; if (outProcessed < avail_out || (outProcessed == avail_out && self->max_length != -1)) break; if (self->max_length != -1) { PyErr_SetString(PyExc_ValueError, "not enough input data for decompression"); DEC_AND_NULL(result); goto exit; } avail_out -= outProcessed; // Output buffer is full, might be more data for decompression if (_PyString_Resize(&result, outsize+BLOCK_SIZE) != 0) goto exit; avail_out += BLOCK_SIZE; tmp = (unsigned char *)PyString_AS_STRING(result) + outsize; } if (outsize != PyString_GET_SIZE(result)) _PyString_Resize(&result, outsize); exit: return result; }
static PyObject *pylzma_decomp_decompress(CCompatDecompressionObject *self, PyObject *args) { PyObject *result=NULL; char *data; PARSE_LENGTH_TYPE length, old_length; PY_LONG_LONG start_total_out; int res; PY_LONG_LONG max_length=BLOCK_SIZE; if (!PyArg_ParseTuple(args, "s#|L", &data, &length, &max_length)) return NULL; if (max_length < 0) { PyErr_SetString(PyExc_ValueError, "bufsize must be greater than zero"); return NULL; } start_total_out = self->stream.totalOut; if (self->unconsumed_length > 0) { self->unconsumed_tail = (char *)realloc(self->unconsumed_tail, self->unconsumed_length + length); self->stream.next_in = (Byte *)self->unconsumed_tail; memcpy(self->stream.next_in + self->unconsumed_length, data, length); } else self->stream.next_in = (Byte *)data; self->stream.avail_in = self->unconsumed_length + length; if (max_length && max_length < length) length = max_length; if (!(result = PyBytes_FromStringAndSize(NULL, length))) return NULL; self->stream.next_out = (unsigned char *) PyBytes_AS_STRING(result); self->stream.avail_out = length; Py_BEGIN_ALLOW_THREADS res = lzmaCompatDecode(&self->stream); Py_END_ALLOW_THREADS while (res == LZMA_OK && self->stream.avail_out == 0) { if (max_length && length >= max_length) break; old_length = length; length <<= 1; if (max_length && length > max_length) length = max_length; if (_PyBytes_Resize(&result, length) < 0) goto exit; self->stream.avail_out = length - old_length; self->stream.next_out = (Byte *) PyBytes_AS_STRING(result) + old_length; Py_BEGIN_ALLOW_THREADS res = lzmaCompatDecode(&self->stream); Py_END_ALLOW_THREADS } if (res == LZMA_NOT_ENOUGH_MEM) { // out of memory during decompression PyErr_NoMemory(); DEC_AND_NULL(result); goto exit; } else if (res == LZMA_DATA_ERROR) { PyErr_SetString(PyExc_ValueError, "data error during decompression"); DEC_AND_NULL(result); goto exit; } else if (res != LZMA_OK && res != LZMA_STREAM_END) { PyErr_Format(PyExc_ValueError, "unknown return code from lzmaDecode: %d", res); DEC_AND_NULL(result); goto exit; } /* Not all of the compressed data could be accomodated in the output buffer of specified size. Return the unconsumed tail in an attribute.*/ if (max_length != 0) { if (self->stream.avail_in > 0) { if (self->stream.avail_in != self->unconsumed_length) self->unconsumed_tail = (char *)realloc(self->unconsumed_tail, self->stream.avail_in); if (!self->unconsumed_tail) { PyErr_NoMemory(); DEC_AND_NULL(result); goto exit; } memcpy(self->unconsumed_tail, self->stream.next_in, self->stream.avail_in); } else FREE_AND_NULL(self->unconsumed_tail); self->unconsumed_length = self->stream.avail_in; } /* The end of the compressed data has been reached, so set the unused_data attribute to a string containing the remainder of the data in the string. Note that this is also a logical place to call inflateEnd, but the old behaviour of only calling it on flush() is preserved. */ if (res == LZMA_STREAM_END) { Py_XDECREF(self->unused_data); /* Free original empty string */ self->unused_data = PyBytes_FromStringAndSize((char *) self->stream.next_in, self->stream.avail_in); if (self->unused_data == NULL) { PyErr_NoMemory(); DEC_AND_NULL(result); goto exit; } } _PyBytes_Resize(&result, self->stream.totalOut - start_total_out); exit: return result; }
static PyObject * pylzma_decomp_decompress(CDecompressionObject *self, PyObject *args) { PyObject *result=NULL; unsigned char *data; Byte *next_in, *next_out; int length, res, bufsize=BLOCK_SIZE; SizeT avail_in; SizeT inProcessed, outProcessed; ELzmaStatus status; if (!PyArg_ParseTuple(args, "s#|i", &data, &length, &bufsize)){ return NULL; } if (bufsize <= 0) { PyErr_SetString(PyExc_ValueError, "bufsize must be greater than zero"); return NULL; } if (self->unconsumed_length > 0) { self->unconsumed_tail = (unsigned char *) realloc(self->unconsumed_tail, self->unconsumed_length + length); next_in = (unsigned char *) self->unconsumed_tail; memcpy(next_in + self->unconsumed_length, data, length); } else { next_in = data; } if (self->need_properties) { if ((self->unconsumed_length + length) < LZMA_PROPS_SIZE) { // we need enough bytes to read the properties self->unconsumed_tail = (unsigned char *) realloc(self->unconsumed_tail, self->unconsumed_length + length); if (self->unconsumed_tail == NULL) { PyErr_NoMemory(); return NULL; } memcpy(self->unconsumed_tail + self->unconsumed_length, data, length); self->unconsumed_length += length; return PyString_FromString(""); } self->unconsumed_length += length; res = LzmaDec_Allocate(&self->state, next_in, LZMA_PROPS_SIZE, &allocator); if (res != SZ_OK) { PyErr_SetString(PyExc_TypeError, "Incorrect stream properties"); return NULL; } next_in += LZMA_PROPS_SIZE; self->unconsumed_length -= LZMA_PROPS_SIZE; if (self->unconsumed_length > 0) { if (self->unconsumed_tail == NULL) { // No remaining data yet self->unconsumed_tail = (unsigned char *) malloc(self->unconsumed_length); if (self->unconsumed_tail == NULL) { PyErr_NoMemory(); return NULL; } memcpy(self->unconsumed_tail, next_in, self->unconsumed_length); next_in = self->unconsumed_tail; } else { // Skip properties in remaining data memmove(self->unconsumed_tail, self->unconsumed_tail+LZMA_PROPS_SIZE, self->unconsumed_length); self->unconsumed_tail = next_in = (unsigned char *) realloc(self->unconsumed_tail, self->unconsumed_length); if (self->unconsumed_tail == NULL) { PyErr_NoMemory(); return NULL; } } } else { FREE_AND_NULL(self->unconsumed_tail); } self->need_properties = 0; LzmaDec_Init(&self->state); } else { self->unconsumed_length += length; } avail_in = self->unconsumed_length; if (avail_in == 0) { // no more bytes to decompress return PyString_FromString(""); } result = PyString_FromStringAndSize(NULL, bufsize); if (result == NULL) { PyErr_NoMemory(); goto exit; } next_out = (unsigned char *) PyString_AS_STRING(result); Py_BEGIN_ALLOW_THREADS // Decompress until EOS marker is reached inProcessed = avail_in; outProcessed = bufsize; res = LzmaDec_DecodeToBuf(&self->state, next_out, &outProcessed, next_in, &inProcessed, LZMA_FINISH_ANY, &status); Py_END_ALLOW_THREADS self->total_out += outProcessed; next_in += inProcessed; avail_in -= inProcessed; if (res != SZ_OK) { DEC_AND_NULL(result); PyErr_SetString(PyExc_ValueError, "data error during decompression"); goto exit; } // Not all of the compressed data could be accomodated in the output buffer // of specified size. Return the unconsumed tail in an attribute. if (avail_in > 0) { if (self->unconsumed_tail == NULL) { // data are in "data" self->unconsumed_tail = (unsigned char *) malloc(avail_in); if (self->unconsumed_tail == NULL) { Py_DECREF(result); PyErr_NoMemory(); goto exit; } memcpy(self->unconsumed_tail, next_in, avail_in); } else { memmove(self->unconsumed_tail, next_in, avail_in); self->unconsumed_tail = (unsigned char *) realloc(self->unconsumed_tail, avail_in); } } else { FREE_AND_NULL(self->unconsumed_tail); } self->unconsumed_length = avail_in; _PyString_Resize(&result, outProcessed); exit: return result; }
static PyObject * pylzma_decomp_flush(CDecompressionObject *self, PyObject *args) { PyObject *result=NULL; int res; SizeT avail_out, outsize; unsigned char *tmp; SizeT inProcessed, outProcessed; ELzmaStatus status; if (self->max_length != -1) { avail_out = self->max_length - self->total_out; } else { avail_out = BLOCK_SIZE; } if (avail_out == 0) { // no more remaining data return PyString_FromString(""); } result = PyString_FromStringAndSize(NULL, avail_out); if (result == NULL) { return NULL; } tmp = (unsigned char *)PyString_AS_STRING(result); outsize = 0; while (1) { Py_BEGIN_ALLOW_THREADS if (self->unconsumed_length == 0) { // No remaining data inProcessed = 0; outProcessed = avail_out; res = LzmaDec_DecodeToBuf(&self->state, tmp, &outProcessed, (Byte *) "", &inProcessed, LZMA_FINISH_ANY, &status); } else { // Decompress remaining data inProcessed = self->unconsumed_length; outProcessed = avail_out; res = LzmaDec_DecodeToBuf(&self->state, tmp, &outProcessed, self->unconsumed_tail, &inProcessed, LZMA_FINISH_ANY, &status); self->unconsumed_length -= inProcessed; if (self->unconsumed_length > 0) memmove(self->unconsumed_tail, self->unconsumed_tail + inProcessed, self->unconsumed_length); else FREE_AND_NULL(self->unconsumed_tail); } Py_END_ALLOW_THREADS if (res != SZ_OK) { PyErr_SetString(PyExc_ValueError, "data error during decompression"); DEC_AND_NULL(result); goto exit; } if (!outProcessed && self->max_length != -1 && self->total_out < self->max_length) { PyErr_SetString(PyExc_ValueError, "data error during decompression"); DEC_AND_NULL(result); goto exit; } self->total_out += outProcessed; outsize += outProcessed; if (outProcessed < avail_out || (outProcessed == avail_out && self->max_length != -1)) { break; } if (self->max_length != -1) { PyErr_SetString(PyExc_ValueError, "not enough input data for decompression"); DEC_AND_NULL(result); goto exit; } avail_out -= outProcessed; // Output buffer is full, might be more data for decompression if (_PyString_Resize(&result, outsize+BLOCK_SIZE) != 0) { goto exit; } avail_out += BLOCK_SIZE; tmp = (unsigned char *)PyString_AS_STRING(result) + outsize; } if (outsize != PyString_GET_SIZE(result)) { _PyString_Resize(&result, outsize); } exit: return result; }