mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix GH-11242: Use dynamic buffer for large length in stream mem copy
This commit is contained in:
4
NEWS
4
NEWS
@@ -22,6 +22,10 @@ PHP NEWS
|
|||||||
. Fixed GH-11573 (RecursiveDirectoryIterator::hasChildren is slow).
|
. Fixed GH-11573 (RecursiveDirectoryIterator::hasChildren is slow).
|
||||||
(nielsdos)
|
(nielsdos)
|
||||||
|
|
||||||
|
- Streams:
|
||||||
|
. Implemented GH-11242 (_php_stream_copy_to_mem: Allow specifying a maximum
|
||||||
|
length without allocating a buffer of that size). (Jakub Zelenka)
|
||||||
|
|
||||||
06 Jul 2023, PHP 8.3.0alpha3
|
06 Jul 2023, PHP 8.3.0alpha3
|
||||||
|
|
||||||
- Core:
|
- Core:
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
--TEST--
|
||||||
|
Test file_get_contents() function with large length parameter
|
||||||
|
--INI--
|
||||||
|
memory_limit=128M
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$file_path = __DIR__ . '/file_get_contents_with_large_length_content.txt';
|
||||||
|
$file_content = str_repeat('a', 50000);
|
||||||
|
file_put_contents($file_path, $file_content);
|
||||||
|
|
||||||
|
// test lenght limiting
|
||||||
|
$result = file_get_contents($file_path, length: 500000000);
|
||||||
|
var_dump($result === $file_content);
|
||||||
|
|
||||||
|
// test lenght limiting
|
||||||
|
$result = file_get_contents($file_path, length: 40000);
|
||||||
|
var_dump($result === str_repeat('a', 40000));
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
unlink(__DIR__ . '/file_get_contents_with_large_length_content.txt');
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
bool(true)
|
||||||
|
bool(true)
|
||||||
@@ -1489,7 +1489,7 @@ PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int
|
|||||||
{
|
{
|
||||||
ssize_t ret = 0;
|
ssize_t ret = 0;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
size_t len = 0, max_len;
|
size_t len = 0, buflen;
|
||||||
int step = CHUNK_SIZE;
|
int step = CHUNK_SIZE;
|
||||||
int min_room = CHUNK_SIZE / 4;
|
int min_room = CHUNK_SIZE / 4;
|
||||||
php_stream_statbuf ssbuf;
|
php_stream_statbuf ssbuf;
|
||||||
@@ -1503,7 +1503,7 @@ PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int
|
|||||||
maxlen = 0;
|
maxlen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxlen > 0) {
|
if (maxlen > 0 && maxlen < 4 * CHUNK_SIZE) {
|
||||||
result = zend_string_alloc(maxlen, persistent);
|
result = zend_string_alloc(maxlen, persistent);
|
||||||
ptr = ZSTR_VAL(result);
|
ptr = ZSTR_VAL(result);
|
||||||
while ((len < maxlen) && !php_stream_eof(src)) {
|
while ((len < maxlen) && !php_stream_eof(src)) {
|
||||||
@@ -1537,20 +1537,30 @@ PHPAPI zend_string *_php_stream_copy_to_mem(php_stream *src, size_t maxlen, int
|
|||||||
* by a downsize of the buffer, overestimate by the step size (which is
|
* by a downsize of the buffer, overestimate by the step size (which is
|
||||||
* 8K). */
|
* 8K). */
|
||||||
if (php_stream_stat(src, &ssbuf) == 0 && ssbuf.sb.st_size > 0) {
|
if (php_stream_stat(src, &ssbuf) == 0 && ssbuf.sb.st_size > 0) {
|
||||||
max_len = MAX(ssbuf.sb.st_size - src->position, 0) + step;
|
buflen = MAX(ssbuf.sb.st_size - src->position, 0) + step;
|
||||||
|
if (maxlen > 0 && buflen > maxlen) {
|
||||||
|
buflen = maxlen;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
max_len = step;
|
buflen = step;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = zend_string_alloc(max_len, persistent);
|
result = zend_string_alloc(buflen, persistent);
|
||||||
ptr = ZSTR_VAL(result);
|
ptr = ZSTR_VAL(result);
|
||||||
|
|
||||||
// TODO: Propagate error?
|
// TODO: Propagate error?
|
||||||
while ((ret = php_stream_read(src, ptr, max_len - len)) > 0){
|
while ((ret = php_stream_read(src, ptr, buflen - len)) > 0) {
|
||||||
len += ret;
|
len += ret;
|
||||||
if (len + min_room >= max_len) {
|
if (len + min_room >= buflen) {
|
||||||
result = zend_string_extend(result, max_len + step, persistent);
|
if (maxlen == len) {
|
||||||
max_len += step;
|
break;
|
||||||
|
}
|
||||||
|
if (maxlen > 0 && buflen + step > maxlen) {
|
||||||
|
buflen = maxlen;
|
||||||
|
} else {
|
||||||
|
buflen += step;
|
||||||
|
}
|
||||||
|
result = zend_string_extend(result, buflen, persistent);
|
||||||
ptr = ZSTR_VAL(result) + len;
|
ptr = ZSTR_VAL(result) + len;
|
||||||
} else {
|
} else {
|
||||||
ptr += ret;
|
ptr += ret;
|
||||||
|
|||||||
Reference in New Issue
Block a user