Re: [RFC] Allow calls to global functions in constant expressions
| From: | Mike Schinkel | Date: | Mon, 10 Feb 2020 04:10:00 +0000 |
| Subject: | Re: [RFC] Allow calls to global functions in constant expressions | ||
| References: | 1 2 3 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-108433@lists.php.net to get a copy of this message | ||
> On Feb 9, 2020, at 8:34 PM, tyson andre <tysonandre775@hotmail.com> wrote:
>
>> 1. Why again are MyClass::methodName() not considered for the non-whitelist vote?
>>
>> Seems to me a developer would be more inclined to implement the expressions that define the
>> class constant's value in a method of the class than in an external function.
>
> My reasons for doing this were to keep the scope small and easy to implement,
> and work on an RFC for methods immediately after if the vote for allowing arbitrary functions
> passed.
>
> The other concern was the edge case
static::method_name() in
> class constants,
> but call_user_func(['static',
> 'method_name']) or
> array_map('static::method_name', VALS)
> causes the same issues.
>
> This leads me to a blocker I've discovered with this implementation calling without a
> whitelist:
> The way PHP resolves the scope is to look for the closest closure or user-defined function,
> then to extract the class of that function. (in zend_get_executed_scope).
> I thought the scope would work because const X = self::Y works,
> but it turns out ZEND_AST_CLASS_CONST is special cased in AST evaluation.
> My current ideas for fixing this (for class constants and property defaults):
> (Parameter defaults, static variables, and global constants should already have reasonable
> scopes)
>
> 1. Wrap all of the calls the engine is making in a byte copy of call_user_func, but with the
> property zend_class_entry *scope set, so that
> zend_get_executed_scope will see that frame's scope and use it instead of the caller's
> scope.
> 2. Add a fake stack frame that acts as if an extra closure (bound to the declaring class's
> scope) was being evaluated.
> 3. Add a brand new function.
>
> If I don't do that, then constant/property evaluation uses the scope of the caller, not
> the class
>
> ```
> class MyClass {
> public static function example() {}
> const X = call_user_func('self::example');
> }
> // this throws in the current implementation
> // due to no active class scope, and that's a bug
> echo MyClass::X;
> ```
>
> If I (or anyone else) can't figure out how to implement the fix, or the fix has issues,
> I might remove the secondary vote from the RFC and just vote on the whitelist,
> which excluded functions accepting callables.
> If anyone comes up with a working implementation for a fix (including exception handling),
> I'd like to know.
>
Thanks for the reply.
>> 2. Do we really want to add a standard library function 53 characters long?
>>
>> Can we not come up with a more concise name than
>> get_defined_functions_allowed_in_constant_expressions(), like maybe get_const_expr_funcs() or
>> get_const_expressions()?
>
> I was planning to change it if I thought of a better name.
> For get_const_expr_funcs(), I'd think it would be important to be consistent about
> naming in the standard library.
> get_const_expr_functions() would work, though.
Oh, okay. But don't you think the 'consistent naming in PHP' ship sailed eons ago?!?
(Sorry, I just could not resist! :-)
-Mike