symfony / polyfill

PHP polyfills

Home Page:https://symfony.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

str_contains behaviour differs from php8 behaviour

PatrickRose opened this issue · comments

It looks like the PHP8 behaviour for str_contains actually silently accepts a null value (casting it to the empty string), whereas the polyfill doesn't. See this comparison on 3v4l, where you can see that the polyfill throws a TypeError but PHP8 doesn't. The same is probably true for the other str methods, but I haven't confirmed it yet.

Happy to send a PR (possibly just easiest to remove the types from the params?)

@PatrickRose Good catch!
Unfortunately, removing the typehint will not help as strpos([], 'test') produces a warning instead of TypeError. The simplest solution I see is changing the method definition to function str_contains(string $haystack = null, string $needle): bool but that doesn't seem elegant.

Ah, of course. Forgot about that behaviour!

Looks like it's the same for $needle as well - here's a 3v4l that checks all the methods and both params. str_starts_with / str_ends_with looks like it might be harder to fix, though I think just manually casting inside those methods might be enough to fix?

I think the method definition should be function str_contains(?string $haystack, ?string $needle), which keeps the previous behaviour about making them required but handles the null.

Shall I get a PR together?

Absolutely no pressure btw, but what's the release schedule for polyfills? We spotted this because we got hit by it, so it'd be great if the fix could be released quickly (but we can easily work around it in our code)

Well, for now, nobody submitted a PR with a fix. So there is nothing to release yet.

Releases are done when needed. There is no fixed schedule.

Thanks @stof - I'll get a PR together now.

Isn't this issue a PHP8 one? Shouldn't PHP8 also reject null, since the types are not nullable?

Can you please open a bug report to bugs.php.net?

Simple reproducer:

function my_str_starts_with(string $haystack, string $needle): bool
{
    return true;
}

var_dump(str_starts_with(null, 'abc'));
var_dump(my_str_starts_with(null, 'abc'));

the second call fails but the first succeeds, unless strict more is enabled.

@stof also raised this in the linked PR. I'm not too familiar with how it works on an internal level, but my guess is that weak mode just casts the args to the relevant type in a way that can't be replicated in userland.

I'm happy to open a bug but it feels like it could possibly be a major BC break since that would need to be applied to all internal functions?

I think it's worth discussing with php-internals yes, please open a bug report there. Userland should be able to polyfill to me...

/cc @nikic in case you have some bandwidth to have a look here.

Yes, this is an open bug in the way scalar types are treated by internal functions. I expect it will get deprecated in PHP 8.1, once I pick up php/php-src#4227 again.

For the purposes of the polyfill, I would recommend using a normal string type. I don't think it makes sense to be bug-compatible with PHP in this regard.

It's been closed as a won't fix on the bug tracker and since we have to choose between making it work the same for strict_mode=1 and making it match strict_mode=0 then it probably makes sense to go with the strict_mode=1 version as the library currently does.

Thanks for reporting and investigating!