diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2020-09-21 16:09:17 +0200 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2020-09-21 16:09:17 +0200 |
commit | 6fa2493789f8f05c7a53eca803227fcfb1bf2573 (patch) | |
tree | 92bcd4e140b9b20795d64df791ac717600a3d9d6 /main/streams/streams.c | |
parent | e95fa3eb0ce97d952598f599052a837ba90f2df2 (diff) | |
parent | 19c844594e40d79cea016b54f9ab3a367440b4c9 (diff) | |
download | php-git-6fa2493789f8f05c7a53eca803227fcfb1bf2573.tar.gz |
Merge branch 'PHP-7.4' into master
* PHP-7.4:
Fix mmap copying
Diffstat (limited to 'main/streams/streams.c')
-rw-r--r-- | main/streams/streams.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/main/streams/streams.c b/main/streams/streams.c index 686427bc96..b14c6fa396 100644 --- a/main/streams/streams.c +++ b/main/streams/streams.c @@ -1566,29 +1566,48 @@ PHPAPI int _php_stream_copy_to_stream_ex(php_stream *src, php_stream *dest, size if (php_stream_mmap_possible(src)) { char *p; - size_t mapped; - p = php_stream_mmap_range(src, php_stream_tell(src), maxlen, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); + do { + size_t chunk_size = (maxlen == 0 || maxlen > PHP_STREAM_MMAP_MAX) ? PHP_STREAM_MMAP_MAX : maxlen; + size_t mapped; - if (p) { - ssize_t didwrite = php_stream_write(dest, p, mapped); - if (didwrite < 0) { - *len = 0; - return FAILURE; - } + p = php_stream_mmap_range(src, php_stream_tell(src), chunk_size, PHP_STREAM_MAP_MODE_SHARED_READONLY, &mapped); + + if (p) { + ssize_t didwrite; + + if (php_stream_seek(src, mapped, SEEK_CUR) != 0) { + php_stream_mmap_unmap(src); + break; + } + + didwrite = php_stream_write(dest, p, mapped); + if (didwrite < 0) { + *len = haveread; + return FAILURE; + } - php_stream_mmap_unmap_ex(src, mapped); + php_stream_mmap_unmap(src); - *len = didwrite; + *len = haveread += didwrite; - /* we've got at least 1 byte to read - * less than 1 is an error - * AND read bytes match written */ - if (mapped > 0 && mapped == didwrite) { - return SUCCESS; + /* we've got at least 1 byte to read + * less than 1 is an error + * AND read bytes match written */ + if (mapped == 0 || mapped != didwrite) { + return FAILURE; + } + if (mapped < chunk_size) { + return SUCCESS; + } + if (maxlen != 0) { + maxlen -= mapped; + if (maxlen == 0) { + return SUCCESS; + } + } } - return FAILURE; - } + } while (p); } while(1) { |