[php-src] PHP-8.6: Merge branch 'PHP-8.5' into PHP-8.6

From: Date: Sun, 04 Oct 2026 14:39:54 +0000
Subject: [php-src] PHP-8.6: Merge branch 'PHP-8.5' into PHP-8.6
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-141914@lists.php.net to get a copy of this message
Author: Ilia Alshanetsky (iliaal) Date: 2026-10-04T10:24:19-04:00 Commit: https://github.com/php/php-src/commit/11c752bab60f993f9537eca64c94ab2230530021 Raw diff: https://github.com/php/php-src/commit/11c752bab60f993f9537eca64c94ab2230530021.diff Merge branch 'PHP-8.5' into PHP-8.6 * PHP-8.5: ext/standard: Reject incomplete sha1_file reads Changed paths: A ext/standard/tests/strings/sha1_file_stream_error.phpt M NEWS M ext/standard/sha1.c Diff: diff --git a/NEWS b/NEWS index 992c885fc427..99882674dae3 100644 --- a/NEWS +++ b/NEWS @@ -123,6 +123,10 @@ PHP NEWS an illegal key). (David Carlier) . Fixed memory leak when load_wsdl_ex() failed to load. (DanielEScherzer) +- Standard: + . Fixed sha1_file() returning a digest for incomplete data after a stream + read failure. (Ilia Alshanetsky) + - Tidy: . Fixed a use-after-free when a tidyNode is used after its document is reparsed. (Ilia Alshanetsky) diff --git a/ext/standard/sha1.c b/ext/standard/sha1.c index 4832756f577a..b6fb10adcaf8 100644 --- a/ext/standard/sha1.c +++ b/ext/standard/sha1.c @@ -82,10 +82,16 @@ PHP_FUNCTION(sha1_file) PHP_SHA1Update(&context, buf, n); } + bool failed = n < 0 || !php_stream_eof(stream); + PHP_SHA1Final(digest, &context); php_stream_close(stream); + if (failed) { + RETURN_FALSE; + } + if (raw_output) { RETURN_STRINGL((char *) digest, 20); } else { diff --git a/ext/standard/tests/strings/sha1_file_stream_error.phpt b/ext/standard/tests/strings/sha1_file_stream_error.phpt new file mode 100644 index 000000000000..751cf5e7240c --- /dev/null +++ b/ext/standard/tests/strings/sha1_file_stream_error.phpt @@ -0,0 +1,77 @@ +--TEST-- +sha1_file() returns false when a stream read fails +--FILE-- +<?php +class TestStream +{ + public $context; + private string $mode; + private int $position = 0; + + public function stream_open(string $path): bool + { + $this->mode = substr($path, strlen('test://')); + + return true; + } + + public function stream_read(int $count): string|false + { + $position = $this->position++; + if ($this->mode === 'error') { + return false; + } + if ($this->mode === 'empty' || $this->mode === 'stalled') { + return ''; + } + if ($this->mode === 'short') { + return substr('prefix', $position * 2, 2); + } + if ($position === 0) { + return 'prefix'; + } + + return $this->mode === 'prefix-error' ? false : ''; + } + + public function stream_eof(): bool + { + return $this->mode === 'empty' + || ($this->mode === 'eof' && $this->position > 1) + || ($this->mode === 'short' && $this->position >= 3); + } +} + +stream_wrapper_register('test', TestStream::class); + +foreach (['error', 'prefix-error', 'stalled', 'prefix-stalled', 'empty', 'eof', 'short'] as $mode) { + echo "$mode: "; + var_dump(sha1_file("test://$mode")); + echo "$mode (raw): "; + $result = sha1_file("test://$mode", true); + var_dump(is_string($result) ? bin2hex($result) : $result); +} + +echo "directory: "; +var_dump(@sha1_file(__DIR__)); +echo "directory (raw): "; +$result = @sha1_file(__DIR__, true); +var_dump(is_string($result) ? bin2hex($result) : $result); +?> +--EXPECT-- +error: bool(false) +error (raw): bool(false) +prefix-error: bool(false) +prefix-error (raw): bool(false) +stalled: bool(false) +stalled (raw): bool(false) +prefix-stalled: bool(false) +prefix-stalled (raw): bool(false) +empty: string(40) "da39a3ee5e6b4b0d3255bfef95601890afd80709" +empty (raw): string(40) "da39a3ee5e6b4b0d3255bfef95601890afd80709" +eof: string(40) "b4ebfe34d0fa97f0dd2bb1234fad8f59805f4e8d" +eof (raw): string(40) "b4ebfe34d0fa97f0dd2bb1234fad8f59805f4e8d" +short: string(40) "b4ebfe34d0fa97f0dd2bb1234fad8f59805f4e8d" +short (raw): string(40) "b4ebfe34d0fa97f0dd2bb1234fad8f59805f4e8d" +directory: bool(false) +directory (raw): bool(false)

« previous php.cvs (#141914) next »