@@ -57,6 +57,9 @@ struct php_xz_stream_data_t {
5757
5858 /* Compression level used. */
5959 unsigned long level ;
60+
61+ /* The maximum amount of memory that can be used when decompressing. */
62+ uint64_t memory ;
6063};
6164/* }}} */
6265
@@ -68,6 +71,7 @@ static int php_xz_decompress(struct php_xz_stream_data_t *self)
6871{
6972 lzma_stream * strm = & self -> strm ;
7073 lzma_action action = LZMA_RUN ;
74+ lzma_ret ret ;
7175
7276 if (strm -> avail_in == 0 && !php_stream_eof (self -> stream )) {
7377#if PHP_VERSION_ID >= 70400
@@ -78,20 +82,15 @@ static int php_xz_decompress(struct php_xz_stream_data_t *self)
7882 strm -> avail_in = read ;
7983#else
8084 strm -> avail_in = php_stream_read (self -> stream , (char * )self -> in_buf , self -> in_buf_sz );
81- strm -> next_in = self -> in_buf ;
8285#endif
86+ strm -> next_in = self -> in_buf ;
8387 }
8488
85- if (lzma_code (strm , action ) != LZMA_OK ) {
89+ ret = lzma_code (strm , action );
90+ if (ret != LZMA_OK && ret != LZMA_STREAM_END ) {
8691 return -1 ;
8792 }
8893
89- if (strm -> avail_out == 0 && self -> out_buf_idx == strm -> next_out ) {
90- /* All bytes in the output buffer have been read. */
91- strm -> next_out = self -> out_buf_idx = self -> out_buf ;
92- strm -> avail_out = self -> out_buf_sz ;
93- }
94-
9594 return 0 ;
9695}
9796/* }}} */
@@ -135,8 +134,7 @@ static int php_xz_init_decoder(struct php_xz_stream_data_t *self)
135134{
136135 lzma_stream * strm = & self -> strm ;
137136
138- uint64_t mem = INI_INT ("xz.max_memory" );
139- if (lzma_auto_decoder (strm , mem ? mem : UINT64_MAX , LZMA_CONCATENATED ) != LZMA_OK ) {
137+ if (lzma_auto_decoder (strm , self -> memory ? self -> memory : UINT64_MAX , LZMA_CONCATENATED ) != LZMA_OK ) {
140138 return 0 ;
141139 }
142140
@@ -202,6 +200,7 @@ static size_t php_xziop_read(php_stream *stream, char *buf, size_t count)
202200 struct php_xz_stream_data_t * self = (struct php_xz_stream_data_t * ) stream -> abstract ;
203201 lzma_stream * strm = & self -> strm ;
204202
203+
205204 size_t to_read = count , have_read = 0 ;
206205
207206 while (to_read > 0 ) {
@@ -214,8 +213,12 @@ static size_t php_xziop_read(php_stream *stream, char *buf, size_t count)
214213 memcpy (buf + have_read , self -> out_buf_idx , strm -> next_out - self -> out_buf_idx );
215214 have_read += strm -> next_out - self -> out_buf_idx ;
216215 to_read -= strm -> next_out - self -> out_buf_idx ;
217- self -> out_buf_idx = strm -> next_out ;
218- if (strm -> next_out == self -> out_buf_idx ) {
216+
217+ if (strm -> avail_out ) {
218+ self -> out_buf_idx = strm -> next_out ;
219+ } else {
220+ /* All bytes in the output buffer have been read. */
221+ self -> out_buf_idx = strm -> next_out ;
219222 self -> out_buf_idx = strm -> next_out = self -> out_buf ;
220223 strm -> avail_out = self -> out_buf_sz ;
221224 }
@@ -226,6 +229,7 @@ static size_t php_xziop_read(php_stream *stream, char *buf, size_t count)
226229 return have_read ;
227230 }
228231
232+
229233 if (php_xz_decompress (self ) < 0 ) {
230234#if PHP_VERSION_ID >= 70400
231235 if (!have_read ) {
@@ -362,16 +366,14 @@ php_stream_ops php_stream_xzio_ops = {
362366php_stream * php_stream_xzopen (php_stream_wrapper * wrapper , const char * path , const char * mode_pass , int options , zend_string * * opened_path , php_stream_context * context STREAMS_DC )
363367{
364368 char mode [64 ];
365- unsigned long level = 6 ;
369+ zend_ulong level = INI_INT ("xz.compression_level" );;
370+ zend_ulong mem = INI_INT ("xz.max_memory" );
371+
366372 php_stream * stream = NULL , * innerstream = NULL ;
367373
368374 strncpy (mode , mode_pass , sizeof (mode ));
369375 mode [sizeof (mode ) - 1 ] = '\0' ;
370376
371- /* The pointer below is freed even though it is `const` because it was
372- manually allocated in `xzopen`.. */
373- efree ((char * ) mode_pass );
374-
375377 /* Split compression level and mode. */
376378 char * colonp = strchr (mode , ':' );
377379 if (colonp ) {
@@ -393,6 +395,16 @@ php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path, con
393395 path += 16 ;
394396 }
395397
398+ if (context ) {
399+ zval * tmpzval ;
400+ if (NULL != (tmpzval = php_stream_context_get_option (context , "xz" , "compression_level" ))) {
401+ level = zval_get_long (tmpzval );
402+ }
403+ if (NULL != (tmpzval = php_stream_context_get_option (context , "xz" , "max_memory" ))) {
404+ mem = zval_get_long (tmpzval );
405+ }
406+ }
407+
396408 innerstream = php_stream_open_wrapper_ex (path , mode , STREAM_MUST_SEEK | options | STREAM_WILL_CAST , opened_path , context );
397409
398410 if (innerstream ) {
@@ -402,6 +414,7 @@ php_stream *php_stream_xzopen(php_stream_wrapper *wrapper, const char *path, con
402414 self -> stream = innerstream ;
403415 self -> fd = fd ;
404416 self -> level = level ;
417+ self -> memory = mem ;
405418 strncpy (self -> mode , mode , sizeof (self -> mode ));
406419 stream = php_stream_alloc_rel (& php_stream_xzio_ops , self , 0 , mode );
407420
0 commit comments