[PHP-CVS] [php-src] master: Fix GH-23082: unserialize_callback_func can no longer be reset to its empty default at runtime (#23096)

[email protected] (Gina Peter Banyard via GitHub)
Newsgroups php.cvs
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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.