Commit 403bf75d832 for php.net

commit 403bf75d83265e535bef19bfda72915132f57072
Merge: c46e63ffadf 2a339c24d0c
Author: Weilin Du <weilindu@php.net>
Date:   Tue Jun 23 23:41:11 2026 +0800

    Merge branch 'PHP-8.4' into PHP-8.5

    * PHP-8.4:
      ext/phar: Fix .phar-prefixed non-magic directory handling (#22372)

diff --cc NEWS
index 89cec7cd311,060dc91e80a..6347408e5c6
--- a/NEWS
+++ b/NEWS
@@@ -18,9 -7,14 +18,16 @@@ PH
      fallback locale when a language tag cannot be canonicalized. (Weilin Du)
    . Fixed memory leaks when calling Collator::__construct() or
      Spoofchecker::__construct() twice. (Weilin Du)
 +  . Fixed memory leak when calling IntlListFormatter::__construct() twice.
 +    (Weilin Du)

+ - Phar:
+   . Fixed inconsistent handling of the magic ".phar" directory. Paths such as
+     "/.phar" remain protected, while non-magic paths that merely start with
+     ".phar" are handled consistently across file and directory creation,
+     copying, ArrayAccess, stream lookup, directory iteration and extraction.
+     (Weilin Du)
+
  - Reflection:
    . Fixed bug GH-22324 (Ignore leading namespace separator in
      ReflectionParameter::__construct()). (jorgsowa)
diff --cc ext/phar/dirstream.c
index c5aa292200e,e28f4f97727..baeb504df5e
--- a/ext/phar/dirstream.c
+++ b/ext/phar/dirstream.c
@@@ -158,9 -178,10 +158,9 @@@ static php_stream *phar_make_dirstream(
  	ALLOC_HASHTABLE(data);
  	zend_hash_init(data, 64, NULL, NULL, 0);

- 	if ((*dir == '/' && dirlen == 1 && (manifest->nNumOfElements == 0)) || (dirlen >= sizeof(".phar")-1 && !memcmp(dir, ".phar", sizeof(".phar")-1))) {
+ 	if ((*dir == '/' && dirlen == 1 && (manifest->nNumOfElements == 0)) || phar_path_is_magic_phar_ex(dir, dirlen)) {
  		/* make empty root directory for empty phar */
  		/* make empty directory for .phar magic directory */
 -		efree(dir);
  		return php_stream_alloc(&phar_dir_ops, data, NULL, "r");
  	}

@@@ -175,8 -204,11 +175,8 @@@

  		if (*dir == '/') {
  			/* root directory */
- 			if (zend_string_starts_with_literal(str_key, ".phar")) {
+ 			if (phar_is_magic_phar(str_key)) {
  				/* do not add any magic entries to this directory */
 -				if (SUCCESS != zend_hash_move_forward(manifest)) {
 -					break;
 -				}
  				continue;
  			}

diff --cc ext/phar/phar_object.c
index e407cc8dbbc,a1736f221e2..8e7155bacf4
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@@ -4177,7 -4161,7 +4160,7 @@@ static zend_result phar_extract_file(bo
  		return SUCCESS;
  	}

- 	if (zend_string_starts_with_literal(entry->filename, ".phar")) {
 -	if (phar_path_is_magic_phar_ex(entry->filename, entry->filename_len)) {
++	if (phar_is_magic_phar(entry->filename)) {
  		return SUCCESS;
  	}
  	/* strip .. from path and restrict it to be under dest directory */