projects/aports·blob master · refs

150 lines · 4.1 KiB

1Patch-Source: https://github.com/kjdev/php-ext-zstd/pull/110
2Report success from the compress.zstd:// stream close handlers.
3
4Both close handlers returned EOF unconditionally. Since PHP 8.6.0RC1
5(php/php-src@c07cc8502c0, bug #60110) fclose(), file_put_contents() and
6copy() propagate a non-zero close result as false, so every write through
7the wrapper was reported as a failure.
8
9diff --git a/tests/streams_10.phpt b/tests/streams_10.phpt
10new file mode 100644
11index 0000000..05d32c1
12--- /dev/null
13+++ b/tests/streams_10.phpt
14@@ -0,0 +1,48 @@
15+--TEST--
16+compress.zstd streams report a successful close
17+--FILE--
18+<?php
19+$file = dirname(__FILE__) . '/streams_10.out';
20+$plain = dirname(__FILE__) . '/streams_10.txt';
21+
22+// As of PHP 8.6, fclose(), file_put_contents() and copy() return false when
23+// closing the stream fails, so the close handler has to report success.
24+$data = str_repeat('abcd', 1024);
25+
26+echo "Compress\n";
27+
28+$fp = fopen('compress.zstd://' . $file, 'w');
29+var_dump($fp !== false);
30+var_dump(fwrite($fp, $data) === strlen($data));
31+var_dump(fclose($fp));
32+
33+echo "Decompress\n";
34+
35+$fp = fopen('compress.zstd://' . $file, 'r');
36+var_dump($fp !== false);
37+var_dump(stream_get_contents($fp) === $data);
38+var_dump(fclose($fp));
39+
40+echo "Copy\n";
41+
42+file_put_contents($plain, $data);
43+var_dump(copy($plain, 'compress.zstd://' . $file));
44+var_dump(file_get_contents('compress.zstd://' . $file) === $data);
45+
46+@unlink($file);
47+@unlink($plain);
48+?>
49+===DONE===
50+--EXPECT--
51+Compress
52+bool(true)
53+bool(true)
54+bool(true)
55+Decompress
56+bool(true)
57+bool(true)
58+bool(true)
59+Copy
60+bool(true)
61+bool(true)
62+===DONE===
63diff --git a/zstd.c b/zstd.c
64index f0891e0..3c6f0fd 100644
65--- a/zstd.c
66+++ b/zstd.c
67@@ -841,9 +841,13 @@ static int php_zstd_decomp_close(php_stream *stream, int close_handle)
68 return EOF;
69 }
70
71+ int ret = 0;
72+
73 if (close_handle) {
74 if (self->stream) {
75- php_stream_close(self->stream);
76+ if (php_stream_close(self->stream)) {
77+ ret = EOF;
78+ }
79 self->stream = NULL;
80 }
81 }
82@@ -854,7 +858,7 @@ static int php_zstd_decomp_close(php_stream *stream, int close_handle)
83 efree(self);
84 stream->abstract = NULL;
85
86- return EOF;
87+ return ret;
88 }
89
90 static int php_zstd_comp_flush_or_end(php_zstd_stream_data *self, int end)
91@@ -872,9 +876,15 @@ static int php_zstd_comp_flush_or_end(php_zstd_stream_data *self, int end)
92 if (ZSTD_isError(res)) {
93 ZSTD_WARNING("zstd: %s", ZSTD_getErrorName(res));
94 ret = EOF;
95+ break;
96+ }
97+ if (self->ctx.output.pos
98+ && (size_t) php_stream_write(self->stream, self->ctx.output.dst,
99+ self->ctx.output.pos)
100+ != self->ctx.output.pos) {
101+ ret = EOF;
102+ break;
103 }
104- php_stream_write(self->stream,
105- self->ctx.output.dst, self->ctx.output.pos);
106 } while (res > 0);
107
108 return ret;
109@@ -897,11 +907,13 @@ static int php_zstd_comp_close(php_stream *stream, int close_handle)
110 return EOF;
111 }
112
113- php_zstd_comp_flush_or_end(self, 1);
114+ int ret = php_zstd_comp_flush_or_end(self, 1);
115
116 if (close_handle) {
117 if (self->stream) {
118- php_stream_close(self->stream);
119+ if (php_stream_close(self->stream)) {
120+ ret = EOF;
121+ }
122 self->stream = NULL;
123 }
124 }
125@@ -911,7 +923,7 @@ static int php_zstd_comp_close(php_stream *stream, int close_handle)
126 efree(self);
127 stream->abstract = NULL;
128
129- return EOF;
130+ return ret;
131 }
132
133
134@@ -997,8 +1009,14 @@ php_zstd_comp_write(php_stream *stream, const char *buf, size_t count)
135 return -1;
136 #endif
137 }
138- php_stream_write(self->stream,
139- self->ctx.output.dst, self->ctx.output.pos);
140+ if (self->ctx.output.pos
141+ && (size_t) php_stream_write(self->stream, self->ctx.output.dst,
142+ self->ctx.output.pos)
143+ != self->ctx.output.pos) {
144+#if PHP_VERSION_ID >= 70400
145+ return -1;
146+#endif
147+ }
148
149 } while (res > 0);
150