[php-src] Issue #23082: unserialize_callback_func can no longer be reset to its empty default at runtime
[email protected] (nicolas-grekas)
| Newsgroups | php.bugs |
|---|---|
| Message-ID | <[email protected]> |
Issue: https://github.com/php/php-src/issues/23082
Author: nicolas-grekas
### Description
Since c82acefe470e0444540c63d2329d8cc675d5777c, the `unserialize_callback_func` INI entry uses `OnUpdateStrNotEmpty` instead of `OnUpdateString`. `OnUpdateStrNotEmpty` returns `FAILURE` for an empty value, so the entry can no longer be set back to its default empty value at runtime.
`ini_set()` returns `false` and leaves the previous value in place, silently. Since the default value is empty, this breaks the usual save/restore idiom: the callback stays installed process-wide and fires for unrelated `unserialize()` calls later on.
The following code:
```php
<?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:{}');
```
Resulted in this output:
```
string(0) ""
bool(false)
string(11) "my_callback"
callback fired for SomeNotExistingClass
Warning: unserialize(): Function my_callback() hasn't defined the class it was called for in /tmp/repro.php on line 13
```
But I expected this output instead:
```
string(0) ""
string(11) "my_callback"
string(0) ""
```
`ini_set('unserialize_callback_func', null)` fails the same way.
`ini_restore('unserialize_callback_func')` still works, so it is usable as a workaround, but it resets to the php.ini value rather than to the saved one.
The change looks unintended: the commit message only mentions avoiding a reallocation, `php.ini-production` and `php.ini-development` still ship `unserialize_callback_func =` empty, and there is no `UPGRADING`/`NEWS` entry. This is currently breaking Symfony on the 8.6 nightly, where the idiom is used in Cache, Config, Messenger, Security and VarExporter.
Note that `output_handler` received the same `OnUpdateString` -> `OnUpdateStrNotEmpty` swap in e0221be81e3, though it is `PHP_INI_PERDIR|PHP_INI_SYSTEM` so the runtime impact is not the same.
### PHP Version
PHP 8.6.0-dev (master, 5d588761922). Works as expected on 8.5.8.
### Operating System
Linux