Commit b77b50508bb for php.net

commit b77b50508bb606c686ea3e902f96de26054258a0
Author: Ilia Alshanetsky <ilia@ilia.ws>
Date:   Sat Apr 18 08:10:44 2026 -0400

    phar: restore is_link handler in phar_intercept_functions_shutdown

    phar_intercept_functions_init hooks 22 built-in functions via
    PHAR_INTERCEPT. phar_intercept_functions_shutdown restores all of them
    via PHAR_RELEASE except is_link, which was simply missing from the list.

    On MSHUTDOWN the is_link entry in CG(function_table) retains the phar
    intercept handler. In a persistent SAPI, if the module is reloaded, the
    second MINIT saves PHP_FN(phar_is_link) as orig_is_link, and any
    subsequent is_link() call recurses infinitely.

    Closes GH-21800

diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c
index f1b2b0eba1e..9d83f740d50 100644
--- a/ext/phar/func_interceptors.c
+++ b/ext/phar/func_interceptors.c
@@ -932,6 +932,7 @@ void phar_intercept_functions_shutdown(void)
 	PHAR_RELEASE(fopen);
 	PHAR_RELEASE(file_get_contents);
 	PHAR_RELEASE(is_file);
+	PHAR_RELEASE(is_link);
 	PHAR_RELEASE(is_dir);
 	PHAR_RELEASE(opendir);
 	PHAR_RELEASE(file_exists);
diff --git a/ext/phar/tests/phar-is-link-intercept.phpt b/ext/phar/tests/phar-is-link-intercept.phpt
new file mode 100644
index 00000000000..f81f1ae425d
--- /dev/null
+++ b/ext/phar/tests/phar-is-link-intercept.phpt
@@ -0,0 +1,29 @@
+--TEST--
+phar: is_link() intercept correctly delegates for non-symlink phar entries
+--EXTENSIONS--
+phar
+--INI--
+phar.readonly=0
+phar.require_hash=0
+--FILE--
+<?php
+$fname = __DIR__ . '/' . basename(__FILE__, '.php') . '.phar';
+$phar = new Phar($fname);
+$phar->addFromString('file.txt', 'hello');
+$phar->setStub('<?php
+Phar::interceptFileFuncs();
+echo "regular entry (not a symlink): ";
+var_dump(is_link("file.txt"));
+echo "missing entry: ";
+var_dump(is_link("nonexistent.txt"));
+echo "absolute phar:// path (bypasses intercept): ";
+var_dump(is_link("phar://" . __FILE__ . "/file.txt"));
+__HALT_COMPILER(); ?>');
+include $fname;
+?>
+--CLEAN--
+<?php @unlink(__DIR__ . '/' . basename(__FILE__, '.clean.php') . '.phar'); ?>
+--EXPECT--
+regular entry (not a symlink): bool(false)
+missing entry: bool(false)
+absolute phar:// path (bypasses intercept): bool(false)