diff --git a/setup.py b/setup.py index 328f7e1..9814c29 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,17 @@ #!/usr/bin/env python -from setuptools import setup, find_packages, Extension +from distutils.core import setup, Extension +import sys VERSION = (0, 7, 0) VERSION_STR = ".".join([str(x) for x in VERSION]) +kwarg=dict() +if sys.version_info >= (2, 7): + kwarg['setup_requires']=["nose>=1.0"] + kwarg['test_suite'] = "nose.collector" + setup( name='lz4', version=VERSION_STR, @@ -14,7 +20,7 @@ author='Steeve Morin', author_email='steeve.morin@gmail.com', url='https://github.com/steeve/python-lz4', - packages=find_packages('src'), + packages=[], package_dir={'': 'src'}, ext_modules=[ Extension('lz4', [ @@ -23,7 +29,7 @@ 'src/python-lz4.c' ], extra_compile_args=[ "-std=c99", - "-O3", +# "-O3", "-Wall", "-W", "-Wundef", @@ -31,8 +37,6 @@ "-DLZ4_VERSION=\"r119\"", ]) ], - setup_requires=["nose>=1.0"], - test_suite = "nose.collector", classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: BSD License', @@ -42,5 +46,6 @@ 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.3', - ], + ], + **kwarg ) diff --git a/src/python-lz4.c b/src/python-lz4.c index 45fe995..9dde906 100644 --- a/src/python-lz4.c +++ b/src/python-lz4.c @@ -125,6 +125,53 @@ static PyObject *py_lz4_uncompress(PyObject *self, PyObject *args) { return result; } +/* + * access to the original lz4_decompress_safe() function + * expect 3 arguments + * - a compressed string in raw format (without the size header) + * - inputSize, the number of bytes to use from the compressed string, + * if zero then use all the string + * - maxOutputSize, the size of the output buffer, if too small then + * raise a ValueError exception, if too big then resized to match + * the uncompressed size. + */ +static PyObject *py_lz4_decompress_safe(PyObject *self, PyObject *args) { + PyObject *result; + const char *source; + int source_size; + int inputSize; + int maxOutputSize; + + if (!PyArg_ParseTuple(args, "s#ii", &source, &source_size, &inputSize, &maxOutputSize)) { + return NULL; + } + + if (inputSize > source_size) { + PyErr_SetString(PyExc_ValueError, "inputSize bigger than source length"); + return NULL; + } + + if (inputSize == 0) { + inputSize = source_size; + } + + result = PyBytes_FromStringAndSize(NULL, maxOutputSize); + if (result != NULL) { + char *dest = PyBytes_AS_STRING(result); + int osize = LZ4_decompress_safe(source, dest, inputSize, maxOutputSize); + if (osize < 0) { + PyErr_Format(PyExc_ValueError, "corrupt input at byte %d", -osize); + Py_CLEAR(result); + } + if (osize < maxOutputSize) { + if (_PyBytes_Resize(&result, osize) < 0) { + return NULL; + } + } + } + return result; +} + static PyMethodDef Lz4Methods[] = { {"LZ4_compress", py_lz4_compress, METH_VARARGS, COMPRESS_DOCSTRING}, {"LZ4_uncompress", py_lz4_uncompress, METH_VARARGS, UNCOMPRESS_DOCSTRING}, @@ -134,6 +181,7 @@ static PyMethodDef Lz4Methods[] = { {"decompress", py_lz4_uncompress, METH_VARARGS, UNCOMPRESS_DOCSTRING}, {"dumps", py_lz4_compress, METH_VARARGS, COMPRESS_DOCSTRING}, {"loads", py_lz4_uncompress, METH_VARARGS, UNCOMPRESS_DOCSTRING}, + {"LZ4_decompress_safe", py_lz4_decompress_safe, METH_VARARGS, LZ4_DECOMPRESS_SAFE_DOCSTRING}, {NULL, NULL, 0, NULL} }; diff --git a/src/python-lz4.h b/src/python-lz4.h index 70e81ac..b404bd5 100644 --- a/src/python-lz4.h +++ b/src/python-lz4.h @@ -33,12 +33,14 @@ static PyObject *py_lz4_compress(PyObject *self, PyObject *args); static PyObject *py_lz4_uncompress(PyObject *self, PyObject *args); +static PyObject *py_lz4_decompress_safe(PyObject *self, PyObject *args); PyMODINIT_FUNC initlz4(void); #define COMPRESS_DOCSTRING "Compress string, returning the compressed data.\nRaises an exception if any error occurs." #define COMPRESSHC_DOCSTRING COMPRESS_DOCSTRING "\n\nCompared to compress, this gives a better compression ratio, but is much slower." #define UNCOMPRESS_DOCSTRING "Decompress string, returning the uncompressed data.\nRaises an exception if any error occurs." +#define LZ4_DECOMPRESS_SAFE_DOCSTRING "Decompress raw string, returning the uncompressed data.\nRaises an exception if any error occurs." #if defined(_WIN32) && defined(_MSC_VER) # define inline __inline