Repository navigation
Conversation
Girgias
left a comment
There was a problem hiding this comment.
Surely it makes more sense to fix this once inside of zend_fcc_dtor() rather than every call site with confusing code with zero comment about why a copy is needed, especially as this function already sets the FCC to empty_fcall_info_cache.
I would appreciate a bit more global thinking.
|
Thanks, that makes sense. I’ll rework the fix so the FCC is cleared centrally in zend_fcc_dtor() before releasing the referenced objects, and keep the libxml regression test to verify the original issue. |
|
Moving the reset to the top of $ctx = stream_context_create();
class N {
public function __invoke() {}
public function __destruct() {
global $ctx;
echo count(stream_context_get_params($ctx)), "\n";
}
}
stream_context_set_params($ctx, ['notification' => new N()]);
stream_context_set_params($ctx, ['notification' => function () {}]);Same for |
|
The replace path still leaks if the old loader's destructor registers a loader: after the detach, class D { public function __destruct() { var_dump(libxml_get_external_entity_loader()); libxml_set_external_entity_loader(fn() => null); } }
$d = new D();
$f = function () use ($d) {};
unset($d);
libxml_set_external_entity_loader($f);
unset($f);
libxml_set_external_entity_loader(fn() => 1);Installing the new callback before releasing the old one avoids it: zend_fcall_info_cache old_fcc = LIBXML(entity_loader_callback);
LIBXML(entity_loader_callback) = empty_fcall_info_cache;
if (ZEND_FCI_INITIALIZED(fci)) { /* argument not null */
zend_fcc_dup(&LIBXML(entity_loader_callback), &fcc);
}
if (ZEND_FCC_INITIALIZED(old_fcc)) {
zend_fcc_dtor(&old_fcc);
}This should target master, since bailouts from destructors aren't backported. The test can run in-process with |
Fixes #24763.
A bailout during destruction of
LIBXML(entity_loader_callback)can interruptzend_fcc_dtor()before the stored FCC is cleared, leaving the module-global callback in a stale state.This change detaches the FCC from
LIBXML(entity_loader_callback)before destroying it, both when replacing the external entity loader and during libxml request shutdown.A regression test is included.
Validation performed:
libxml_get_external_entity_loader()returnednullin all 10 runs.ext/libxmltest suite on patched PHP-8.4: 23 passed, 0 failed, 8 skipped.git diff --check: clean.