Commit c7ffb825aa1 for php.net

commit c7ffb825aa105bea7f6f32dea480fbe3dc49e009
Author: ndossche <7771979+ndossche@users.noreply.github.com>
Date:   Mon Sep 21 21:06:14 2026 +0200

    Fix OSS-Fuzz #5674034779193344: Read of uninitialized memory in is_cacheable_stream_path()

    memcmp() will read inside the padding bytes of the zend_string, which
    are not initialized. This is not exploitable because they're 8 padding
    bytes and the length of "file://" and "phar://" is 7 so the mismatch
    happens at the length-of-the-string index; returning non-0 anyway.

    Closes GH-23830.

diff --git a/NEWS b/NEWS
index f76464756f3..95e545f919a 100644
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,8 @@ PHP                                                                        NEWS
     FCCs and inlining). (ndossche)
   . Fixed bug GH-23693 (Tracing JIT produces wrong results for a guard on a
     loop-invariant addition). (Ilia Alshanetsky)
+  . Fixed OSS-Fuzz #5674034779193344 (Read of uninitialized memory in
+    is_cacheable_stream_path()). (ndossche)

 - PDO:
   . Fixed PDOStatement::getColumnMeta() reading out of bounds for an invalid
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 221cc55d9f6..8a285928cc0 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -195,10 +195,10 @@ static time_t zend_accel_get_time(void)
 # define zend_accel_get_time() time(NULL)
 #endif

-static inline bool is_cacheable_stream_path(const char *filename)
+static inline bool is_cacheable_stream_path(const zend_string *filename)
 {
-	return memcmp(filename, "file://", sizeof("file://") - 1) == 0 ||
-	       memcmp(filename, "phar://", sizeof("phar://") - 1) == 0;
+	return zend_string_starts_with_literal(filename, "file://") ||
+	       zend_string_starts_with_literal(filename, "phar://");
 }

 /* O+ overrides PHP chdir() function and remembers the current working directory
@@ -1205,7 +1205,7 @@ zend_string *accel_make_persistent_key(zend_string *str)
 	if (IS_ABSOLUTE_PATH(path, path_length)) {
 		/* pass */
 	} else if (UNEXPECTED(php_is_stream_path(path))) {
-		if (!is_cacheable_stream_path(path)) {
+		if (!is_cacheable_stream_path(str)) {
 			return NULL;
 		}
 		/* pass */
@@ -1903,7 +1903,7 @@ static zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int
 	bool from_memory; /* if the script we've got is stored in SHM */

 	if (php_is_stream_path(ZSTR_VAL(file_handle->filename)) &&
-	    !is_cacheable_stream_path(ZSTR_VAL(file_handle->filename))) {
+	    !is_cacheable_stream_path(file_handle->filename)) {
 		return accelerator_orig_compile_file(file_handle, type);
 	}

@@ -2047,7 +2047,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
 				return accelerator_orig_compile_file(file_handle, type);
 			}
 			persistent_script = zend_accel_hash_find(&ZCSG(hash), key);
-		} else if (UNEXPECTED(php_is_stream_path(ZSTR_VAL(file_handle->filename)) && !is_cacheable_stream_path(ZSTR_VAL(file_handle->filename)))) {
+		} else if (UNEXPECTED(php_is_stream_path(ZSTR_VAL(file_handle->filename)) && !is_cacheable_stream_path(file_handle->filename))) {
 			ZCG(cache_opline) = NULL;
 			ZCG(cache_persistent_script) = NULL;
 			return accelerator_orig_compile_file(file_handle, type);