Skip to content
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

Add warnings about numeric strings in scientific notation #4407

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions language/types/numeric-strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,33 @@ NUM_STRING ({INT_NUM_STRING} | {FLOAT_NUM_STRING})
any characters.
</para>

<note>
<warning>
<para>
Any string that contains the letter <literal>E</literal> (case insensitive)
bounded by numbers will be seen as a number expressed in scientific notation.
This can produce unexpected results.
This can produce unexpected results, particularly when the significand
(the part of the number before the <literal>E</literal>) is <literal>0</literal>.
To avoid problems in comparisons, strings should usually be compared using
the identity operator (<literal>===</literal>) or string comparison functions
like <function>strcmp</function> and <function>hash_compare</function>.
<programlisting role="php">
<![CDATA[
<?php
var_dump("0D1" == "000"); // false, "0D1" is not scientific notation
var_dump("0E1" == "000"); // true, "0E1" is 0 * (10 ^ 1), or 0
var_dump("2E1" == "020"); // true, "2E1" is 2 * (10 ^ 1), or 20
var_dump("0E1234" == "0E5678"); // true, because 0 * anything is 0
/*
Functions that return hexidecimal strings, like hashing functions,
can return strings that look like scientific notation with 0 as
the significand.
*/
var_dump(md5('240610708') == md5('QNKCDZO')); // true
?>
]]>
</programlisting>
</para>
</note>
</warning>

<sect2 xml:id="language.types.numeric-string.conversion">
<title>Strings used in numeric contexts</title>
Expand Down
17 changes: 17 additions & 0 deletions language/types/type-juggling.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@
If the value cannot be interpreted a <classname>TypeError</classname> is thrown.
Prior to PHP 7.4.0, an <constant>E_RECOVERABLE_ERROR</constant> was raised.
</simpara>

<warning>
<simpara>
When using the <link linkend="language.operators.comparison">comparison
operator (<literal>==</literal>)</link>,
<link linkend="language.types.numeric-strings">numeric strings</link>
will be compared as numbers instead of as strings.
This means that <literal>"123" == " 123 "</literal> is &true;,
but also that <literal>"0e1234" == "0e5678"</literal> is &true;,
which can cause unexpected behavior when comparing hexidecimal strings
like those from <function>hash</function>.
The identity operator (<literal>===</literal>) or a string comparison
function, such as <function>strcmp</function> or
<function>hash_compare</function>, should be used to avoid unexpected
results.
</simpara>
</warning>
Comment on lines +88 to +103
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in the comparative type juggling section, not the string one.

</sect2>

<sect2>
Expand Down
Loading