Re: Don't compare zero exponentials in strings as equal
| From: | Ben Ramsey | Date: | Wed, 03 Mar 2021 15:36:49 +0000 |
| Subject: | Re: Don't compare zero exponentials in strings as equal | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-113350@lists.php.net to get a copy of this message | ||
> On Mar 3, 2021, at 08:04, Nikita Popov <nikita.ppv@gmail.com> wrote:
>
> Hi internals,
>
> PHP's == comparison semantics for strings have a peculiar edge-case, where
> comparisons of the form "0e123" == "0e456" return true, because they are
> interpreted as floating point zero numbers. This is problematic, because
> strings of that form are usually not numbers, but hex-encoded hashes or
> similar.
>
> I'm wondering if it may make sense to special-case the comparison semantics
> to not consider strings of the form "0e[DIGITS]" equal, unless they are
> exactly equal (i.e., fall back to lexicographical if both sides of the
> comparison are zero exponentials).
>
> Here's a possible implementation:
> https://github.com/php/php-src/pull/6749
>
> Of course, the usual rule that you should always use === still holds, but
> this at least eliminates the most dangerous edge case.
I encountered a similar situation a few years back.
We were testing whether a value was numeric and, if so, adding 0 to it in order to convert it to an
appropriate number type. The code looked something like this:
if (is_numeric($value)) {
$value += 0;
}
We chose not to do an explicit cast because the string could represent a float or an int, so we
wanted the type coercion to do its magic.
We did this before calling
Attachment: [application/pgp-signature] Message signed with OpenPGP signature.asc
json_encode() on the data structure, so that string numbers
coming out of a database would be converted to numbers in JSON. For some reason,
JSON_NUMERIC_CHECK wasn’t giving us what we wanted, but I can’t recall the issue we
were having.
Anyway, we ran into some fun issues with hashes that looked like this:
'131124826899e4096767887418316466'
That value should have remained a string in the JSON output, but is_numeric() returns
true for it, so it became INF.
We were able to come up with a work-around, but it’s not foolproof.
Cheers,
Ben
Attachment: [application/pgp-signature] Message signed with OpenPGP signature.asc