Commit dbd4c29887a for php.net
commit dbd4c29887abcd8a9ec879c6805429e9cd447080
Author: Arnaud Le Blanc <365207+arnaud-lb@users.noreply.github.com>
Date: Tue Aug 25 10:20:32 2026 +0200
PFA: Extend local pointer map after loading PFA from SHM (#23250)
When loading a PFA from SHM we may need to extend the local pointer map because
the PFA may use pointers higher than CG(map_ptr_last). Similar synchronization
happens in inheritance cache or when loading whole scripts.
diff --git a/Zend/tests/partial_application/map_ptr_last.phpt b/Zend/tests/partial_application/map_ptr_last.phpt
new file mode 100644
index 00000000000..1ee70d45735
--- /dev/null
+++ b/Zend/tests/partial_application/map_ptr_last.phpt
@@ -0,0 +1,58 @@
+--TEST--
+PFA and ZCSG(map_ptr_last)
+--CREDITS--
+Ryan @ Calif.io
+--EXTENSIONS--
+pcntl
+--INI--
+opcache.file_update_protection=0
+--SKIPIF--
+<?php
+if (!function_exists('pcntl_fork')) {
+ die("skip no pcntl_fork");
+}
+?>
+--FILE--
+<?php
+
+function f($a, $b) {
+ return new ReflectionClass($a);
+}
+
+function get_pfa() {
+ return f(?, 0);
+}
+
+$pid = pcntl_fork();
+if ($pid) {
+ pcntl_waitpid($pid, $status, 0);
+
+ /* PFA retrieved from SHM, run_time_cache > CG(map_ptr_last) */
+ var_dump(get_pfa()('ReflectionClass'));
+} else {
+ /* Increment ZSCG(map_ptr_last) enough to mandate a realloc in other processes.
+ * We do so by compiling many functions that are guaranteed to allocate a map_ptr. */
+
+ $fd = fopen(__DIR__ . '/map_ptr_last.inc', 'w');
+ fwrite($fd, "<?php\n");
+ for ($i = 0; $i < 4096; $i++) {
+ fprintf($fd, "function pfa_map_ptr_flood_%05d(\$obj) { return \$obj->prop; }\n", $i);
+ }
+ fclose($fd);
+
+ require __DIR__ . '/map_ptr_last.inc';
+
+ /* Compile a PFA */
+ get_pfa()('ReflectionClass');
+}
+
+?>
+--CLEAN--
+<?php
+@unlink(__DIR__ . '/map_ptr_last.inc');
+?>
+--EXPECTF--
+object(ReflectionClass)#%d (1) {
+ ["name"]=>
+ string(15) "ReflectionClass"
+}
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index f4bdcf3e7f7..05fb6700ea7 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -2073,6 +2073,9 @@ const zend_op_array *zend_accel_pfa_cache_get(
zend_emit_recorded_errors_ex(persistent_script->num_warnings,
persistent_script->warnings);
}
+ if (ZCSG(map_ptr_last) > CG(map_ptr_last)) {
+ zend_map_ptr_extend(ZCSG(map_ptr_last));
+ }
}
} else {
op_array = zend_hash_find_ptr(&EG(partial_function_application_cache), key);