-
Notifications
You must be signed in to change notification settings - Fork 7.8k
Check parameters on compact() and throw TypeError if not string or array of strings #6921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check parameters on compact() and throw TypeError if not string or array of strings #6921
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this can land as is in PHP 8.1, however an E_WARNING which will be promoted in PHP 9 will for sure be possible.
Might need to contact the internals list about this
I'd rather it was a |
Shouldn't it error only with Also I wonder about implicit coercion (with strict_types=0 i.e. by default), e.g. |
We don't really have the internal tooling to do that, there is the possibility of using ZPP for a string|array union but the values of the array would be strict type checked all the time anyway. |
The parameters are not coerced by the implementation of compact (as your last 34vl link demonstrates) - the nature of the problem *is* compact's documented parameter and behaviour is `(...array<string>|string)` but in reality it's `(...mixed)` - and it's the weirdness highlighted by your example that my change will prevent with a TypeError :)
…On Wed, 28 Apr 2021, 13:52 Guilliam Xavier, ***@***.***> wrote:
Shouldn't it error only with strict_types=1? like e.g.
https://3v4l.org/AMlZX vs https://3v4l.org/K3cmC
Also I wonder about implicit coercion (with strict_types=0 i.e. by
default), e.g. compact(42, true) vs compact("42", "1")
https://3v4l.org/WGVGr 🤔
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation looks fine, but once again I don't know if a TypeError can just be introduced like that. Ideally this would have been caught for PHP 8.0.
@Girgias cheers for the pointers, it's always good to learn more about the engine from more seasoned contributors, re: |
So there's no way to make the "reality" match the "documented"? 😢 |
Not until we get typed arrays 😄 but at least throwing some explicit error prevents silent bugs - the reason I thought to do this one is because there was an occasion recently, it was one of those things you spend ages trying to hunt down a seemingly obscure bug in your code, only to eventually slap yourself when you realise it was something so obvious, yet so easy to do and so hard to spot. In my case, I had absent-mindedly specified the variables themselves as parameters to |
There always is a way, it's just extremely clunky and last time I thought about doing that @nikic was far from convinced. The main issue is that variadics don't get parsed individually by ZPP it's just an array of zvals, and for the rare cases where variadics are used with scalars might as well be a bit stricter. |
I see, thanks for explaining. Anyway there are other issues like |
As these are actual function arguments (and not, say, the contents of an options array), it's okay to make them follow strict_types semantics. We just don't have ZPP support for this. You'd need to explicitly call |
So @nikic are you suggesting we make that change in this PR, or happy with it as-is? |
I'm not really sure to be honest. I think handling the arguments as |
Hmm, yeah that would be an improvement, OTOH There is another argument, that something like I'd push for the PR as it is to be accepted/merged and |
Linking to mailing list thread for reference: https://externals.io/message/114229 |
@ramsey are you able to retrigger the build? Updated the tests in accordance with the final comments and not sure why the build's failing, it's not related to these changes or tests as far as I can see? |
} ZEND_HASH_FOREACH_END(); | ||
if (Z_REFCOUNTED_P(entry)) { | ||
Z_UNPROTECT_RECURSION_P(entry); | ||
} | ||
} else { | ||
php_error_docref(NULL, E_WARNING, "Argument #%d must be string or array of strings, %s given", pos, zend_zval_type_name(entry)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error message is a bit imprecise when it comes to values in arrays, but I think it's good enough to go on...
compact()
is documented (https://www.php.net/manual/en/function.compact) as a variadic function accepting parameters which are strings or arrays of strings referencing defined symbols.In actuality, passing nonsense parameters e.g.
compact(true, 42)
merely returns an empty array. I propose throwing aTypeError
in these cases, to prevent silent bugs.