Skip to content

Commit 94884eb

Browse files
committed
fix uncompress stream and manage context
1 parent 2f4de24 commit 94884eb

File tree

8 files changed

+96
-23
lines changed

8 files changed

+96
-23
lines changed

tests/xzcode_advanced.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Test `xzencode` and `xzdecode`: big inputs.
33
--SKIPIF--
44
<?php
55
if (!extension_loaded("xz")) {
6-
print("XZ extension is not loaded!");
6+
die("skip XZ extension is not loaded!");
77
}
88
?>
99
--FILE--

tests/xzcode_basic.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Test `xzencode` and `xzdecode`: basic functionality.
33
--SKIPIF--
44
<?php
55
if (!extension_loaded("xz")) {
6-
print("XZ extension is not loaded!");
6+
die("skip XZ extension is not loaded!");
77
}
88
?>
99
--FILE--

tests/xzdecode.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Test `xzdecode` simple case
33
--SKIPIF--
44
<?php
55
if (!extension_loaded("xz")) {
6-
print("XZ extension is not loaded!");
6+
die("skip XZ extension is not loaded!");
77
}
88
?>
99
--FILE--

tests/xzopen_basic.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Test `xzopen`: basic functionality.
33
--SKIPIF--
44
<?php
55
if (!extension_loaded("xz")) {
6-
print("XZ extension is not loaded!");
6+
die("skip XZ extension is not loaded!");
77
}
88
?>
99
--FILE--

tests/xzopen_error.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Test `xzopen`: error conditions.
33
--SKIPIF--
44
<?php
55
if (!extension_loaded("xz")) {
6-
print("XZ extension is not loaded!");
6+
die("skip XZ extension is not loaded!");
77
}
88
?>
99
--FILE--

tests/xzstream.phpt

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
--TEST--
2+
Test lzma stream
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded("xz")) {
6+
die("skip XZ extension is not loaded!");
7+
}
8+
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
9+
?>
10+
--FILE--
11+
<?php
12+
$tmp1 = tempnam(sys_get_temp_dir(), "LZMA");
13+
$tmp2 = tempnam(sys_get_temp_dir(), "LZMA");
14+
$tmp3 = tempnam(sys_get_temp_dir(), "LZMA");
15+
16+
$len0 = filesize(PHP_BINARY);
17+
18+
echo "Compress level 2 ($tmp1)\n";
19+
$opts = [
20+
'xz' => [
21+
'compression_level' => '2',
22+
'max_memory' => 64*1024*1024,
23+
]
24+
];
25+
$ctx = stream_context_create($opts);
26+
copy(PHP_BINARY, "compress.lzma://$tmp1");
27+
$len1 = filesize($tmp1);
28+
var_dump($len1 > 0);
29+
var_dump($len1 <= $len0);
30+
31+
echo "Compress level 9 ($tmp2)\n";
32+
$opts = [
33+
'xz' => [
34+
'compression_level' => '9',
35+
'max_memory' => 64*1024*1024,
36+
]
37+
];
38+
$ctx = stream_context_create($opts);
39+
copy(PHP_BINARY, "compress.lzma://$tmp2", $ctx);
40+
$len2 = filesize($tmp2);
41+
var_dump($len2 > 0);
42+
var_dump($len2 <= $len1);
43+
44+
echo "Uncompress ($tmp3)\n";
45+
copy("compress.lzma://$tmp1", $tmp3);
46+
$len3 = filesize($tmp3);
47+
var_dump($len3 > 0);
48+
var_dump($len3 == $len0);
49+
50+
?>
51+
--EXPECTF--
52+
Compress level 2 (%s)
53+
bool(true)
54+
bool(true)
55+
Compress level 9 (%s)
56+
bool(true)
57+
bool(true)
58+
Uncompress (%s)
59+
bool(true)
60+
bool(true)

tests/xzwrite_basic.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Test function xzwrite() by calling it with its expected arguments
33
--SKIPIF--
44
<?php
55
if (!extension_loaded("xz")) {
6-
print("XZ extension is not loaded!");
6+
die("skip XZ extension is not loaded!");
77
}
88
?>
99
--FILE--

xz_fopen_wrapper.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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 = {
362366
php_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

Comments
 (0)