Commit 06c95e72749 for php

commit 06c95e72749d23b4e5cfc6fad0569701537b0d6e
Merge: bbfdd69f601 19a50604f9d
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date:   Tue Oct 13 18:52:29 2026 +0200

    Merge branch 'PHP-8.4' into PHP-8.5

    * PHP-8.4:
      Fix GH-24289: finfo::file() reports the wrong argument number

diff --cc NEWS
index 73d7145593f,98d3853e0b7..a8b32cd0d65
--- a/NEWS
+++ b/NEWS
@@@ -22,6 -20,12 +22,10 @@@ PH
      (Nicolas Grekas)
    . Fix escape analysis for objects implementing ArrayAccess. (ndossche, Arnaud)

 -- DOM:
 -  . Fixed bug GH-23352 (UAF reading an attribute value node retained across
 -    DOMDocument::adoptNode()). (David Carlier)
 -  . Fixed bug GH-24260 (querySelectorAll() returns duplicate elements for
 -    selector lists). (fivefilters)
++- Fileinfo:
++  . Fixed bug GH-24289 (finfo::file() reports the wrong argument number for
++    an invalid $filename). (Lazizbek Ergashev)
+
  - FPM:
    . Fixed bug GH-24229 (fcgi_close() passes shutdown() a literal 1, which is
      SHUT_RD in WASI). (Ryosuke Ishibashi)
diff --cc ext/fileinfo/fileinfo.c
index baae7571549,e935fb1489f..cc2f7307396
--- a/ext/fileinfo/fileinfo.c
+++ b/ext/fileinfo/fileinfo.c
@@@ -234,79 -283,56 +234,79 @@@ PHP_FUNCTION(finfo_set_flags
  }
  /* }}} */

 -#define FILEINFO_MODE_BUFFER 0
 -#define FILEINFO_MODE_STREAM 1
 -#define FILEINFO_MODE_FILE 2
 -
 -static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mimetype_emu) /* {{{ */
 +static const char* php_fileinfo_from_path(struct magic_set *magic, const zend_string *path, php_stream_context *context)
  {
 -	zend_long options = 0;
 -	char *ret_val = NULL, *buffer = NULL;
 -	size_t buffer_len;
 -	php_fileinfo *finfo = NULL;
 -	zval *zcontext = NULL;
 -	zval *what;
 -	char mime_directory[] = "directory";
 -	struct magic_set *magic = NULL;
 +	ZEND_ASSERT(magic != NULL);
 +	ZEND_ASSERT(path);
 +	ZEND_ASSERT(ZSTR_LEN(path) != 0);
 +	ZEND_ASSERT(!zend_str_has_nul_byte(path));
 +	ZEND_ASSERT(context != NULL);
 +
 +	/* determine if the file is a local file or remote URL */
 +	const char *dummy;
 +	php_stream_statbuf ssb;
 +
 +	const php_stream_wrapper *wrap = php_stream_locate_url_wrapper(ZSTR_VAL(path), &dummy, 0);
 +	if (UNEXPECTED(wrap == NULL)) {
 +		return NULL;
 +	}
 +
 +#ifdef PHP_WIN32
 +	if (php_stream_stat_path_ex(ZSTR_VAL(path), 0, &ssb, context) == SUCCESS) {
 +		if (ssb.sb.st_mode & S_IFDIR) {
 +			return "directory";
 +		}
 +	}
 +#endif

 -	if (mimetype_emu) {
 +	php_stream *stream = php_stream_open_wrapper_ex(ZSTR_VAL(path), "rb", REPORT_ERRORS, NULL, context);
 +	if (!stream) {
 +		return NULL;
 +	}

 -		/* mime_content_type(..) emulation */
 -		if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &what) == FAILURE) {
 -			RETURN_THROWS();
 +	const char *ret_val = NULL;
 +	if (php_stream_stat(stream, &ssb) == SUCCESS) {
 +		if (ssb.sb.st_mode & S_IFDIR) {
 +			ret_val = "directory";
 +		} else {
 +			ret_val = magic_stream(magic, stream);
 +			if (UNEXPECTED(ret_val == NULL)) {
 +				php_error_docref(NULL, E_WARNING, "Failed identify data %d:%s", magic_errno(magic), magic_error(magic));
 +			}
  		}
 +	}

 -		switch (Z_TYPE_P(what)) {
 -			case IS_STRING:
 -				buffer = Z_STRVAL_P(what);
 -				buffer_len = Z_STRLEN_P(what);
 -				mode = FILEINFO_MODE_FILE;
 -				break;
 +	php_stream_close(stream);

 -			case IS_RESOURCE:
 -				mode = FILEINFO_MODE_STREAM;
 -				break;
 +	return ret_val;
 +}

 -			default:
 -				zend_argument_type_error(1, "must be of type resource|string, %s given", zend_zval_value_name(what));
 -				RETURN_THROWS();
 -		}
 +/* Return information about a file. */
 +PHP_FUNCTION(finfo_file)
 +{
 +	zval *self;
 +	zend_string *path = NULL;
 +	zend_long options = 0;
 +	zval *zcontext = NULL;

 -		magic = magic_open(MAGIC_MIME_TYPE);
 -		if (magic_load(magic, NULL) == -1) {
 -			php_error_docref(NULL, E_WARNING, "Failed to load magic database");
 -			goto common;
 -		}
 -	} else {
 -		zval *self;
 -		if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|lr!", &self, finfo_class_entry, &buffer, &buffer_len, &options, &zcontext) == FAILURE) {
 -			RETURN_THROWS();
 -		}
 -		FILEINFO_FROM_OBJECT(finfo, self);
 -		magic = finfo->magic;
 +	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "OP|lr!", &self, finfo_class_entry, &path, &options, &zcontext) == FAILURE) {
 +		RETURN_THROWS();
 +	}
 +
 +	if (!Z_FINFO_P(self)->magic) {
 +		zend_throw_error(NULL, "Invalid finfo object");
 +		RETURN_THROWS();
 +	}
 +
 +	struct magic_set *magic = Z_FINFO_P(self)->magic;
 +
 +	if (UNEXPECTED(ZSTR_LEN(path) == 0)) {
- 		zend_argument_must_not_be_empty_error(2);
++		zend_argument_must_not_be_empty_error(hasThis() ? 1 : 2);
 +		RETURN_THROWS();
 +	}
 +	php_stream_context *context = php_stream_context_from_zval(zcontext, false);
 +	if (!context) {
 +		RETURN_THROWS();
  	}

  	/* Set options for the current file/buffer. */
diff --cc ext/fileinfo/tests/gh24289.phpt
index 00000000000,f33eb0f2372..035fca7e96b
mode 000000,100644..100644
--- a/ext/fileinfo/tests/gh24289.phpt
+++ b/ext/fileinfo/tests/gh24289.phpt
@@@ -1,0 -1,23 +1,23 @@@
+ --TEST--
+ GH-24289 (finfo::file() reports the wrong argument number for an invalid $filename)
+ --EXTENSIONS--
+ fileinfo
+ --FILE--
+ <?php
+
+ $finfo = new finfo();
+ try {
+     var_dump($finfo->file(''));
 -} catch (\ValueError $e) {
 -    echo $e->getMessage() . \PHP_EOL;
++} catch (Throwable $e) {
++    echo $e::class, ": ", $e->getMessage() . \PHP_EOL;
+ }
+ try {
+     var_dump($finfo->file("\0"));
 -} catch (\TypeError $e) {
 -    echo $e->getMessage() . \PHP_EOL;
++} catch (Throwable $e) {
++    echo $e::class, ": ", $e->getMessage() . \PHP_EOL;
+ }
+
+ ?>
+ --EXPECT--
 -finfo::file(): Argument #1 ($filename) must not be empty
 -finfo::file(): Argument #1 ($filename) must not contain any null bytes
++ValueError: finfo::file(): Argument #1 ($filename) must not be empty
++ValueError: finfo::file(): Argument #1 ($filename) must not contain any null bytes