@@ -29,6 +29,9 @@ from .igzip_lib cimport *
2929from libc.stdint cimport UINT64_MAX, UINT32_MAX, uint32_t
3030from cpython.mem cimport PyMem_Malloc, PyMem_Free
3131
32+ cdef extern from " <Python.h>" :
33+ const Py_ssize_t PY_SSIZE_T_MAX
34+
3235ISAL_BEST_SPEED = ISAL_DEF_MIN_LEVEL
3336ISAL_BEST_COMPRESSION = ISAL_DEF_MAX_LEVEL
3437ISAL_DEFAULT_COMPRESSION = 2
@@ -382,6 +385,28 @@ cdef class Decompress:
382385 self .eof = 0
383386 self .is_initialised = 1
384387
388+ cdef save_unconsumed_input(self , object data):
389+ cdef Py_ssize_t old_size, new_size, left_size, offset
390+ cdef unsigned char * data_ptr
391+ if self .stream.block_state == ISAL_BLOCK_FINISH:
392+ if self .stream.avail_in > 0 :
393+ old_size = len (self .unused_data)
394+ data_ptr = data
395+ left_size = data_ptr + len (data) - self .stream.next_in
396+ offset = self .stream.next_in - data_ptr
397+ if offset < 0 :
398+ raise Exception ()
399+ if left_size > (PY_SSIZE_T_MAX - old_size):
400+ raise MemoryError ()
401+ self .unused_data += data[offset:]
402+ if self .stream.avail_in > 0 or self .unconsumed_tail:
403+ data_ptr = data
404+ left_size = data_ptr + len (data) - self .stream.next_in
405+ offset = self .stream.next_in - data_ptr
406+ if offset < 0 :
407+ raise Exception ()
408+ self .unconsumed_tail = data[offset:]
409+
385410 def decompress (self , data , Py_ssize_t max_length = 0 ):
386411
387412 cdef Py_ssize_t total_bytes = 0
@@ -441,24 +466,7 @@ cdef class Decompress:
441466 out.append(obuf[:bytes_written])
442467 if self .stream.block_state == ISAL_BLOCK_FINISH or last_round:
443468 break
444- # Save unconsumed input implementation from zlibmodule.c
445- if self .stream.block_state == ISAL_BLOCK_FINISH:
446- # The end of the compressed data has been reached. Store the
447- # leftover input data in self->unused_data.
448- self .eof = 1
449- if self .stream.avail_in > 0 :
450- unused_bytes = self .stream.avail_in
451- self .unused_data = data[- unused_bytes:]
452- self .stream.avail_in = 0
453- if self .stream.avail_in > 0 or self .unconsumed_tail:
454- # This code handles two distinct cases:
455- # 1. Output limit was reached. Save leftover input in unconsumed_tail.
456- # 2. All input data was consumed. Clear unconsumed_tail.
457- unused_bytes = self .stream.avail_in
458- if unused_bytes == 0 :
459- self .unconsumed_tail = b" "
460- else :
461- self .unconsumed_tail = data[- unused_bytes:]
469+ self .save_unconsumed_input(data)
462470 return b" " .join(out)
463471 finally :
464472 PyMem_Free(obuf)
@@ -500,20 +508,7 @@ cdef class Decompress:
500508 bytes_written = obuflen - self .stream.avail_out
501509 total_bytes += bytes_written
502510 out.append(obuf[:bytes_written])
503- if self .stream.block_state == ISAL_BLOCK_FINISH:
504- # The end of the compressed data has been reached. Store the
505- # leftover input data in self->unused_data.
506- self .eof = 1
507- self .is_initialised = 0
508- if self .stream.avail_in > 0 :
509- unused_bytes = self .stream.avail_in
510- self .unused_data = data[- unused_bytes:]
511- if self .stream.avail_in > 0 or self .unconsumed_tail:
512- # This code handles two distinct cases:
513- # 1. Output limit was reached. Save leftover input in unconsumed_tail.
514- # 2. All input data was consumed. Clear unconsumed_tail.
515- unused_bytes = self .stream.avail_in
516- self .unconsumed_tail = data[- unused_bytes:]
511+ self .save_unconsumed_input(data)
517512 return b" " .join(out)
518513 finally :
519514 PyMem_Free(obuf)
0 commit comments