summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-07-29 10:07:12 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-07-29 10:07:12 +0200
commit9bfda013d308b47610fb23ee565500418a9f3cde (patch)
tree32bb1c54097bfe07c19268f6afc19abbbd133768
parentfec71e3f25ebac450404e2035027d4344d556e9a (diff)
downloadphp-git-9bfda013d308b47610fb23ee565500418a9f3cde.tar.gz
Fixed bug #78340
Even if we know the file size, we still need to read in a loop in case the read call returns an incomplete result. This was less of an issue previously because we did not use the "one large read" approach for non-plain stream wrappers.
-rw-r--r--NEWS4
-rw-r--r--Zend/tests/bug78340.phpt54
-rw-r--r--Zend/zend_stream.c20
3 files changed, 69 insertions, 9 deletions
diff --git a/NEWS b/NEWS
index 43eeb6de46..d04416d347 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 7.4.0beta2
+- Core:
+ . Fixed bug #78340 (Include of stream wrapper not reading whole file).
+ (Nikita)
+
- Iconv:
. Fixed bug #78342 (Bus error in configure test for iconv //IGNORE). (Rainer
Jung)
diff --git a/Zend/tests/bug78340.phpt b/Zend/tests/bug78340.phpt
new file mode 100644
index 0000000000..06acf9ef88
--- /dev/null
+++ b/Zend/tests/bug78340.phpt
@@ -0,0 +1,54 @@
+--TEST--
+Bug #78340: Include of stream wrapper not reading whole file
+--FILE--
+<?php
+
+class lib {
+ public static $files= [];
+
+ private $bytes, $pos;
+
+ function stream_open($path, $mode, $options, $opened_path) {
+ $this->bytes= self::$files[$path];
+ $this->pos= 0;
+ $this->ino= crc32($path);
+ return true;
+ }
+
+ function stream_read($count) {
+ $chunk= substr($this->bytes, $this->pos, $count);
+ $this->pos+= strlen($chunk);
+ return $chunk;
+ }
+
+ function stream_eof() {
+ return $this->pos >= strlen($this->bytes);
+ }
+
+ function stream_close() {
+ $this->bytes= null;
+ }
+
+ function stream_stat() {
+ return [
+ 'dev' => 3632233996,
+ 'size' => strlen($this->bytes),
+ 'ino' => $this->ino
+ ];
+ }
+
+ function stream_set_option($option, $arg1, $arg2) {
+ return false;
+ }
+}
+
+$fill = str_repeat('.', 8192);
+lib::$files['lib://test.php']= '<?php /* '.$fill.' */ function test() { echo "Works!\n"; }';
+stream_wrapper_register('lib', lib::class);
+
+include('lib://test.php');
+test();
+
+?>
+--EXPECT--
+Works!
diff --git a/Zend/zend_stream.c b/Zend/zend_stream.c
index 4dffc31040..3890248a26 100644
--- a/Zend/zend_stream.c
+++ b/Zend/zend_stream.c
@@ -115,7 +115,7 @@ static ssize_t zend_stream_read(zend_file_handle *file_handle, char *buf, size_t
ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t *len) /* {{{ */
{
- size_t size;
+ size_t file_size;
if (file_handle->buf) {
*buf = file_handle->buf;
@@ -142,26 +142,28 @@ ZEND_API int zend_stream_fixup(zend_file_handle *file_handle, char **buf, size_t
file_handle->handle.stream.fsizer = (zend_stream_fsizer_t)zend_stream_stdio_fsizer;
}
- size = zend_stream_fsize(file_handle);
- if (size == (size_t)-1) {
+ file_size = zend_stream_fsize(file_handle);
+ if (file_size == (size_t)-1) {
return FAILURE;
}
- if (size) {
+ if (file_size) {
ssize_t read;
- *buf = safe_emalloc(1, size, ZEND_MMAP_AHEAD);
- read = zend_stream_read(file_handle, *buf, size);
+ size_t size = 0;
+ *buf = safe_emalloc(1, file_size, ZEND_MMAP_AHEAD);
+ while ((read = zend_stream_read(file_handle, *buf + size, file_size - size)) > 0) {
+ size += read;
+ }
if (read < 0) {
efree(*buf);
return FAILURE;
}
file_handle->buf = *buf;
- file_handle->len = read;
+ file_handle->len = size;
} else {
- size_t remain = 4*1024;
+ size_t size = 0, remain = 4*1024;
ssize_t read;
*buf = emalloc(remain);
- size = 0;
while ((read = zend_stream_read(file_handle, *buf + size, remain)) > 0) {
size += read;