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