mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Fix GH-10031: [Stream] STREAM_NOTIFY_PROGRESS over HTTP emitted irregularly for last chunk of data
It's possible that the server already sent in more data than just the headers. Since the stream only accepts progress increments after the headers are processed, the already read data is never added to the process. We account for this by adjusting the progress counter by the difference of already read header data and the body. For the test: Co-authored-by: aetonsi <18366087+aetonsi@users.noreply.github.com> Closes GH-10492.
This commit is contained in:
parent
05bd1423ee
commit
b33fbbfe3d
3 changed files with 61 additions and 0 deletions
2
NEWS
2
NEWS
|
@ -24,6 +24,8 @@ PHP NEWS
|
||||||
source file). (ilutov)
|
source file). (ilutov)
|
||||||
|
|
||||||
- Streams:
|
- Streams:
|
||||||
|
. Fixed bug GH-10031 ([Stream] STREAM_NOTIFY_PROGRESS over HTTP emitted
|
||||||
|
irregularly for last chunk of data). (nielsdos)
|
||||||
. Fixed bug GH-11175 (Stream Socket Timeout). (nielsdos)
|
. Fixed bug GH-11175 (Stream Socket Timeout). (nielsdos)
|
||||||
. Fixed bug GH-11177 (ASAN UndefinedBehaviorSanitizer when timeout = -1
|
. Fixed bug GH-11177 (ASAN UndefinedBehaviorSanitizer when timeout = -1
|
||||||
passed to stream_socket_accept/stream_socket_client). (nielsdos)
|
passed to stream_socket_accept/stream_socket_client). (nielsdos)
|
||||||
|
|
|
@ -955,6 +955,13 @@ out:
|
||||||
if (transfer_encoding) {
|
if (transfer_encoding) {
|
||||||
php_stream_filter_append(&stream->readfilters, transfer_encoding);
|
php_stream_filter_append(&stream->readfilters, transfer_encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* It's possible that the server already sent in more data than just the headers.
|
||||||
|
* We account for this by adjusting the progress counter by the difference of
|
||||||
|
* already read header data and the body. */
|
||||||
|
if (stream->writepos > stream->readpos) {
|
||||||
|
php_stream_notify_progress_increment(context, stream->writepos - stream->readpos, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
|
|
52
ext/standard/tests/streams/gh10031.phpt
Normal file
52
ext/standard/tests/streams/gh10031.phpt
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
--TEST--
|
||||||
|
GH-10031 ([Stream] STREAM_NOTIFY_PROGRESS over HTTP emitted irregularly for last chunk of data)
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test");
|
||||||
|
?>
|
||||||
|
--INI--
|
||||||
|
allow_url_fopen=1
|
||||||
|
--CONFLICTS--
|
||||||
|
server
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$serverCode = <<<'CODE'
|
||||||
|
$fsize = 1000;
|
||||||
|
$chunksize = 99;
|
||||||
|
$chunks = floor($fsize / $chunksize); // 10 chunks * 99 bytes
|
||||||
|
$lastchunksize = $fsize - $chunksize * $chunks; // 1 chunk * 10 bytes
|
||||||
|
|
||||||
|
header("Content-Length: " . $fsize);
|
||||||
|
flush();
|
||||||
|
for ($chunk = 1; $chunk <= $chunks; $chunk++) {
|
||||||
|
echo str_repeat('x', $chunksize);
|
||||||
|
@ob_flush();
|
||||||
|
usleep(50 * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
echo str_repeat('x', $lastchunksize);
|
||||||
|
CODE;
|
||||||
|
|
||||||
|
include __DIR__."/../../../../sapi/cli/tests/php_cli_server.inc";
|
||||||
|
php_cli_server_start($serverCode, null, []);
|
||||||
|
|
||||||
|
$context = stream_context_create(['http' => ['ignore_errors' => true,]]);
|
||||||
|
$lastBytesTransferred = 0;
|
||||||
|
stream_context_set_params($context, ['notification' => function ($code, $s, $m, $mc, $bytes_transferred, $bytes_max)
|
||||||
|
use (&$lastBytesTransferred) {
|
||||||
|
if ($code === STREAM_NOTIFY_FILE_SIZE_IS) echo "expected filesize=$bytes_max".PHP_EOL;
|
||||||
|
$lastBytesTransferred = $bytes_transferred;
|
||||||
|
@ob_flush();
|
||||||
|
}]);
|
||||||
|
|
||||||
|
$get = file_get_contents("http://".PHP_CLI_SERVER_ADDRESS, false, $context);
|
||||||
|
|
||||||
|
echo "got filesize=" . strlen($get) . PHP_EOL;
|
||||||
|
var_dump($lastBytesTransferred);
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
expected filesize=1000
|
||||||
|
got filesize=1000
|
||||||
|
int(1000)
|
Loading…
Add table
Add a link
Reference in a new issue