Fix GH-23232: is_callable('\::method') asks the autoloader for an empty class name - #23233
Fix GH-23232: is_callable('\::method') asks the autoloader for an empty class name#23233spawnia wants to merge 1 commit into
Conversation
Girgias
left a comment
There was a problem hiding this comment.
This seems okay as a fix, might be worse to see if this can be prevent on the call sites for the future.
|
Thanks! I put the guard in Validating at the call sites would mean duplicating "is this even a syntactically possible class name?" in each of them. |
…empty class name A class name consisting solely of the namespace separator passed the length check in zend_lookup_class_ex(), lost its leading backslash and was then looked up and autoloaded as an empty string.
b0d5d4d to
3916faf
Compare
|
For the record, the two userland-side fixes were both declined, which leaves this the only remaining place to fix it — and arguably the right level anyway.
That reasoning points here: the caller handing Composer an empty class name is the engine itself, via |
|
Indeed, autoloading |
|
I'm realising that this is a long standing behavioural change (even if it is dumb) so I'd prefer to only target master for this. |
Fixes GH-23232.
zend_lookup_class_ex()rejects an empty class name, but not a name consisting solely of the namespace separator:"\"passes the length check, gets its leading\stripped, and is then looked up — and autoloaded — as"".That is reachable from userland:
is_callable('\::method')splits at::, takes"\"as the class part and hands it tozend_lookup_class().is_callable('::method')is rejected as an invalid function name earlier, which is where the asymmetry in the issue comes from.A lone
\names no class, so returnNULLbefore consulting the class table or the autoloader.This is observable, not just wasted work: Composer's
ClassLoader::findFileWithExtension()does$first = $class[0];and warnsUninitialized string offset 0when handed'', which in applications that promote warnings to exceptions aborts the request. We hit it in CI through Laravel'sFactory::expandAttributes(), which callsis_callable()on every string attribute — a randomly generated password starting with\::was enough.Targeting
PHP-8.4as the lowest branch still receiving bug fixes.make testpasses onZend/testsandext/standard/tests/general_functions(5085 passed, 0 failed) in a debug build; the new.phptfails without the patch.