[php-src] master: Fix GH-23082: unserialize_callback_func can no longer be reset to its empty default at runtime (#23096)
Gina Peter Banyard via GitHub <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Gina Peter Banyard (Girgias)
Committer: GitHub (web-flow)
Pusher: Girgias
Date: 2026-08-07T12:22:12+01:00
Commit: https://github.com/php/php-src/commit/b25e63d95c0a07c76c84fa2ec40bdbe659fef879
Raw diff: https://github.com/php/php-src/commit/b25e63d95c0a07c76c84fa2ec40bdbe659fef879.diff
Fix GH-23082: unserialize_callback_func can no longer be reset to its empty default at runtime (#23096)
By using OnUpdateStr INI handler rather than OnUpdateStrNotEmpty
Changed paths:
A ext/standard/tests/serialize/unserialize_callback_func/gh23082.phpt
M ext/standard/var_unserializer.re
M main/main.c
Diff:
diff --git a/ext/standard/tests/serialize/unserialize_callback_func/gh23082.phpt b/ext/standard/tests/serialize/unserialize_callback_func/gh23082.phpt
new file mode 100644
index 000000000000..adbc5e892655
--- /dev/null
+++ b/ext/standard/tests/serialize/unserialize_callback_func/gh23082.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug GH-23082: unserialize_callback_func can no longer be reset to its empty default at runtime
+--FILE--
+<?php
+
+function my_callback($name) { echo "callback fired for $name\n"; }
+
+// Save the current value and install our own, the usual save/restore idiom.
+$prev = ini_set('unserialize_callback_func', 'my_callback');
+var_dump($prev);
+
+// Restore it. $prev is "" here, since that is the default value.
+var_dump(ini_set('unserialize_callback_func', $prev));
+var_dump(ini_get('unserialize_callback_func'));
+
+// The callback is still installed and fires for unrelated code.
+$o = unserialize('O:20:"SomeNotExistingClass":0:{}');
+
+?>
+--EXPECT--
+string(0) ""
+string(11) "my_callback"
+string(0) ""
diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re
index 27647c907d3a..eca9660c5605 100644
--- a/ext/standard/var_unserializer.re
+++ b/ext/standard/var_unserializer.re
@@ -1249,7 +1249,7 @@ object ":" uiv ":" ["] {
}
/* Check for unserialize callback */
- if (PG(unserialize_callback_func) == NULL) {
+ if (PG(unserialize_callback_func) == NULL || zend_string_equals(PG(unserialize_callback_func), zend_empty_string)) {
incomplete_class = 1;
ce = PHP_IC_ENTRY;
break;
diff --git a/main/main.c b/main/main.c
index 2eb55c5cff07..0539220de362 100644
--- a/main/main.c
+++ b/main/main.c
@@ -824,7 +824,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("auto_globals_jit", "1", PHP_INI_PERDIR|PHP_INI_SYSTEM, OnUpdateBool, auto_globals_jit, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("short_open_tag", DEFAULT_SHORT_OPEN_TAG, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, short_tags, zend_compiler_globals, compiler_globals)
- STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateStrNotEmpty, unserialize_callback_func, php_core_globals, core_globals)
+ STD_PHP_INI_ENTRY("unserialize_callback_func", NULL, PHP_INI_ALL, OnUpdateStr, unserialize_callback_func, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("serialize_precision", "-1", PHP_INI_ALL, OnSetSerializePrecision, serialize_precision, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("arg_separator.output", "&", PHP_INI_ALL, OnUpdateStrNotEmpty, arg_separator.output, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("arg_separator.input", "&", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateStrNotEmpty, arg_separator.input, php_core_globals, core_globals)