@@ -78,6 +78,7 @@ typedef struct
7878 PyObject_HEAD
7979 z_stream zst ;
8080 PyObject * unused_data ;
81+ PyObject * unconsumed_tail ;
8182 int is_initialised ;
8283} compobject ;
8384
@@ -100,6 +101,15 @@ newcompobject(PyTypeObject *type)
100101 return NULL ;
101102 self -> is_initialised = 0 ;
102103 self -> unused_data = PyString_FromString ("" );
104+ if (self -> unused_data == NULL ) {
105+ Py_DECREF (self );
106+ return NULL ;
107+ }
108+ self -> unconsumed_tail = PyString_FromString ("" );
109+ if (self -> unconsumed_tail == NULL ) {
110+ Py_DECREF (self );
111+ return NULL ;
112+ }
103113 return self ;
104114}
105115
@@ -485,6 +495,7 @@ Comp_dealloc(compobject *self)
485495 if (self -> is_initialised )
486496 deflateEnd (& self - > zst );
487497 Py_XDECREF (self -> unused_data );
498+ Py_XDECREF (self -> unconsumed_tail );
488499 PyObject_Del (self );
489500
490501 LEAVE_ZLIB
@@ -498,6 +509,7 @@ Decomp_dealloc(compobject *self)
498509 if (self -> is_initialised )
499510 inflateEnd (& self - > zst );
500511 Py_XDECREF (self -> unused_data );
512+ Py_XDECREF (self -> unconsumed_tail );
501513 PyObject_Del (self );
502514
503515 LEAVE_ZLIB
@@ -595,27 +607,41 @@ PyZlib_objcompress(compobject *self, PyObject *args)
595607}
596608
597609static char decomp_decompress__doc__ [] =
598- "decompress(data) -- Return a string containing the decompressed version of the data.\n\n"
610+ "decompress(data, max_length) -- Return a string containing\n"
611+ "the decompressed version of the data.\n\n"
599612"After calling this function, some of the input data may still\n"
600613"be stored in internal buffers for later processing.\n"
601- "Call the flush() method to clear these buffers."
614+ "Call the flush() method to clear these buffers.\n"
615+ "If the max_length parameter is specified then the return value will be\n"
616+ "no longer than max_length. Unconsumed input data will be stored in\n"
617+ "the unconsumed_tail attribute."
602618;
603619
604620static PyObject *
605621PyZlib_objdecompress (compobject * self , PyObject * args )
606622{
607- int err , inplen , length = DEFAULTALLOC ;
623+ int err , inplen , old_length , length = DEFAULTALLOC ;
624+ int max_length = 0 ;
608625 PyObject * RetVal ;
609626 Byte * input ;
610627 unsigned long start_total_out ;
611628 int return_error ;
612629 PyObject * inputString ;
613630
614- if (!PyArg_ParseTuple (args , "S:decompress" , & inputString ))
631+ if (!PyArg_ParseTuple (args , "S|i:decompress" , & inputString , & max_length ))
632+ return NULL ;
633+ if (max_length < 0 ) {
634+ PyErr_SetString (PyExc_ValueError ,
635+ "max_length must be greater than zero" );
615636 return NULL ;
637+ }
638+
616639 if (PyString_AsStringAndSize (inputString , (char * * )& input , & inplen ) == -1 )
617640 return NULL ;
618641
642+ /* limit amount of data allocated to max_length */
643+ if (max_length && length > max_length )
644+ length = max_length ;
619645 if (!(RetVal = PyString_FromStringAndSize (NULL , length ))) {
620646 PyErr_SetString (PyExc_MemoryError ,
621647 "Can't allocate memory to compress data" );
@@ -637,23 +663,46 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
637663 err = inflate (& (self -> zst ), Z_SYNC_FLUSH );
638664 Py_END_ALLOW_THREADS
639665
640- /* while Z_OK and the output buffer is full, there might be more output,
641- so extend the output buffer and try again */
666+ /* While Z_OK and the output buffer is full, there might be more output.
667+ So extend the output buffer and try again.
668+ */
642669 while (err == Z_OK && self -> zst .avail_out == 0 ) {
643- if (_PyString_Resize (& RetVal , length << 1 ) == -1 ) {
670+ /* If max_length set, don't continue decompressing if we've already
671+ reached the limit.
672+ */
673+ if (max_length && length >= max_length )
674+ break ;
675+
676+ /* otherwise, ... */
677+ old_length = length ;
678+ length = length << 1 ;
679+ if (max_length && length > max_length )
680+ length = max_length ;
681+
682+ if (_PyString_Resize (& RetVal , length ) == -1 ) {
644683 PyErr_SetString (PyExc_MemoryError ,
645684 "Can't allocate memory to compress data" );
646685 return_error = 1 ;
647686 break ;
648687 }
649- self -> zst .next_out = (unsigned char * )PyString_AsString (RetVal ) + length ;
650- self -> zst .avail_out = length ;
651- length = length << 1 ;
688+ self -> zst .next_out = (unsigned char * )PyString_AsString (RetVal )+ old_length ;
689+ self -> zst .avail_out = length - old_length ;
690+
652691 Py_BEGIN_ALLOW_THREADS
653692 err = inflate (& (self -> zst ), Z_SYNC_FLUSH );
654693 Py_END_ALLOW_THREADS
655694 }
656695
696+ /* Not all of the compressed data could be accomodated in the output buffer
697+ of specified size. Return the unconsumed tail in an attribute.*/
698+ if (max_length ) {
699+ Py_DECREF (self -> unconsumed_tail );
700+ self -> unconsumed_tail = PyString_FromStringAndSize (self -> zst .next_in ,
701+ self -> zst .avail_in );
702+ if (!self -> unconsumed_tail )
703+ return_error = 1 ;
704+ }
705+
657706 /* The end of the compressed data has been reached, so set the unused_data
658707 attribute to a string containing the remainder of the data in the string.
659708 Note that this is also a logical place to call inflateEnd, but the old
@@ -885,6 +934,11 @@ Decomp_getattr(compobject *self, char *name)
885934 Py_INCREF (self -> unused_data );
886935 retval = self -> unused_data ;
887936 }
937+ else if (strcmp (name , "unconsumed_tail ") == 0 )
938+ {
939+ Py_INCREF (self -> unconsumed_tail );
940+ retval = self -> unconsumed_tail ;
941+ }
888942 else
889943 retval = Py_FindMethod (Decomp_methods , (PyObject * )self , name );
890944
0 commit comments