@@ -29,6 +29,9 @@ from .igzip_lib cimport *
29
29
from libc.stdint cimport UINT64_MAX, UINT32_MAX, uint32_t
30
30
from cpython.mem cimport PyMem_Malloc, PyMem_Free
31
31
32
+ cdef extern from " <Python.h>" :
33
+ const Py_ssize_t PY_SSIZE_T_MAX
34
+
32
35
ISAL_BEST_SPEED = ISAL_DEF_MIN_LEVEL
33
36
ISAL_BEST_COMPRESSION = ISAL_DEF_MAX_LEVEL
34
37
ISAL_DEFAULT_COMPRESSION = 2
@@ -382,6 +385,28 @@ cdef class Decompress:
382
385
self .eof = 0
383
386
self .is_initialised = 1
384
387
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
+
385
410
def decompress (self , data , Py_ssize_t max_length = 0 ):
386
411
387
412
cdef Py_ssize_t total_bytes = 0
@@ -441,24 +466,7 @@ cdef class Decompress:
441
466
out.append(obuf[:bytes_written])
442
467
if self .stream.block_state == ISAL_BLOCK_FINISH or last_round:
443
468
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)
462
470
return b" " .join(out)
463
471
finally :
464
472
PyMem_Free(obuf)
@@ -500,20 +508,7 @@ cdef class Decompress:
500
508
bytes_written = obuflen - self .stream.avail_out
501
509
total_bytes += bytes_written
502
510
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)
517
512
return b" " .join(out)
518
513
finally :
519
514
PyMem_Free(obuf)
0 commit comments