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

From: Date: Sun, 04 Oct 2026 14:39:54 +0000
Subject: [php-src] master: Merge branch 'PHP-8.4' into PHP-8.5
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-141915@lists.php.net to get a copy of this message
Author: Ilia Alshanetsky (iliaal) Date: 2026-10-04T10:18:25-04:00 Commit: https://github.com/php/php-src/commit/0c543c52fb662efe92bf6a1b97bab64425e1c736 Raw diff: https://github.com/php/php-src/commit/0c543c52fb662efe92bf6a1b97bab64425e1c736.diff Merge branch 'PHP-8.4' into PHP-8.5 * PHP-8.4: 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 f14d47d2aca5..9e7c1c4907c5 100644 --- a/NEWS +++ b/NEWS @@ -192,6 +192,8 @@ PHP NEWS (Ilia Alshanetsky) - Standard: + . Fixed sha1_file() returning a digest for incomplete data after a stream + read failure. (Ilia Alshanetsky) . Fixed three Windows-only proc_open() defects: an uninitialized PROCESS_INFORMATION, an indeterminate comspec pointer after a failed lookup, and an unchecked CreateFileA() failure. (Ilia Alshanetsky) diff --git a/ext/standard/sha1.c b/ext/standard/sha1.c index 95f2b54d0fd0..7dd801c01514 100644 --- a/ext/standard/sha1.c +++ b/ext/standard/sha1.c @@ -84,10 +84,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 (#141915) next »