rfc:invalid_strings_in_arithmetic

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:invalid_strings_in_arithmetic [2016/01/26 21:17] ajfrfc:invalid_strings_in_arithmetic [2017/09/22 13:28] (current) – external edit 127.0.0.1
Line 1: Line 1:
 ====== PHP RFC: Warn about invalid strings in arithmetic ====== ====== PHP RFC: Warn about invalid strings in arithmetic ======
-  * Version: 1.1+  * Version: 1.1.3
   * Date: 2016-01-08   * Date: 2016-01-08
   * Author: Andrea Faulds, ajf@ajf.me   * Author: Andrea Faulds, ajf@ajf.me
-  * Status: Under Discussion+  * Status: Implemented (PHP 7.1)
   * First Published at: http://wiki.php.net/rfc/invalid_strings_in_arithmetic   * First Published at: http://wiki.php.net/rfc/invalid_strings_in_arithmetic
  
Line 14: Line 14:
  
 ==== New E_NOTICE and E_WARNING ==== ==== New E_NOTICE and E_WARNING ====
-For all arithmetic operators, using a non-numeric string (such as <php>"foobar"</php>) as an operand where a number is expected will produce an [[http://php.net/manual/en/errorfunc.constants.php|E_WARNING]] error, and using a non-well-formed numeric string (such as <php>"10 apples"</php>) will produce an [[http://php.net/manual/en/errorfunc.constants.php|E_NOTICE]] error. For our purposes, the "arithmetic operators" are considered to be the set { ''+ - * / *''''* % << >> | & ^'' }. The bitwise NOT operator ''~'' is not included, because it does not perform automatic numeric string conversion.+For all arithmetic operators, using a non-numeric string (such as <php>"foobar"</php>) as an operand where a number is expected will produce an [[http://php.net/manual/en/errorfunc.constants.php|E_WARNING]] error, and using a non-well-formed numeric string (such as <php>"10 apples"</php>) will produce an [[http://php.net/manual/en/errorfunc.constants.php|E_NOTICE]] error. For our purposes, the "arithmetic operators" are considered to be the set { ''+ - * / *''''* % <''''< >''''> | & ^'' }. The bitwise NOT operator ''~'' is not included, because it does not perform automatic numeric string conversion.
  
 In short, the following code, which currently produces no errors In short, the following code, which currently produces no errors
Line 62: Line 62:
   * [[http://lxr.php.net/s?refs=is_numeric_string_ex&project=PHP_7_0|is_numeric_string_ex]], a Zend Engine function for converting strings to integers or floating-point numbers. It accepts anything ''strtol'' or ''strtod'' accepts, and intelligently chooses whether to convert to an integer or a float. It is the function which produces the "A non well formed numeric string encountered" error.   * [[http://lxr.php.net/s?refs=is_numeric_string_ex&project=PHP_7_0|is_numeric_string_ex]], a Zend Engine function for converting strings to integers or floating-point numbers. It accepts anything ''strtol'' or ''strtod'' accepts, and intelligently chooses whether to convert to an integer or a float. It is the function which produces the "A non well formed numeric string encountered" error.
  
-Operators that can take either an integer or a float (''+ - * / *''''*''), and type checks for function parameters and return types (both ''int'' and ''float'') use ''is_numeric_string_ex''. This means that they can handle numbers in scientific notation, so for example, <php>var_dump(1.2345e9 + 0);</php> results in ''float(1234500000)'', and <php>var_dump(intdiv(1.2345e9, 1));</php> results in ''int(1234500000)''.+Operators that can take either an integer or a float (''+ - * / *''''*''), and type checks for function parameters and return types (both ''int'' and ''float'') use ''is_numeric_string_ex''. This means that they can handle numbers in scientific notation, so for example, <php>var_dump("1.2345e9+ 0);</php> results in ''float(1234500000)'', and <php>var_dump(intdiv("1.2345e9", 1));</php> results in ''int(1234500000)''.
  
-However, the integer operators (''% << >> | & ^'') and the integer type casts (<php>(int)</php> and <php>intval()</php>) both use ''strtol''. ''strtol'' stops reading a string when it hits a character it doesn't accept, so ''-123.45'' is interpreted correctly, as it stops reading at the unaccepted ''.'' and produces ''-123''. But for numbers in scientific notation, this produces the wrong result: when reading ''1.2345e9'', it will stop at ''.'' and produce ''1''. Thus, <php>var_dump((int)"1.2345e9");</php> and <php>var_dump("1.2345e9" | 0);</php> both produce ''int(1)''.+However, the integer operators (''% <''''< >''''> | & ^'') and the integer type casts (<php>(int)</php> and <php>intval()</php>) both use ''strtol''. ''strtol'' stops reading a string when it hits a character it doesn't accept, so ''-123.45'' is interpreted correctly, as it stops reading at the unaccepted ''.'' and produces ''-123''. But for numbers in scientific notation, this produces the wrong result: when reading ''1.2345e9'', it will stop at ''.'' and produce ''1''. Thus, <php>var_dump((int)"1.2345e9");</php> and <php>var_dump("1.2345e9" | 0);</php> both produce ''int(1)''.
  
 This inconsistency is unintuitive, and becomes a greater problem if we add warnings and notices for non-numeric strings, as some operators would tell you strings like ''"1.2345e9"'' and ''"-123.45"'' are non-well-formed, whereas other operators would happily accept such strings. This inconsistency is unintuitive, and becomes a greater problem if we add warnings and notices for non-numeric strings, as some operators would tell you strings like ''"1.2345e9"'' and ''"-123.45"'' are non-well-formed, whereas other operators would happily accept such strings.
  
-To avoid this problem, this RFC proposes use ''is_numeric_string_ex'' instead of ''strtol'' for the integer operators and integer casts, resolving the inconsistency.+To avoid this problem, this RFC proposes to use ''is_numeric_string_ex'' instead of ''strtol'' for the integer operators and integer casts (<php>intval()</php> with <php>$base</php> = 10, <php>(int)</php>, <php>settype()</php>, etc.), resolving the inconsistency. This also affects the Zend Engine C functions ''zval_get_long'' and ''convert_to_long'', and so PHP functions which uses these internal functions are also affected, including <php>decbin()</php>, <php>decoct()</php> and <php>dechex()</php>.
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 100: Line 100:
 ==== To Opcache ==== ==== To Opcache ====
  
-To the best of my knowledge, this does not have any problematic interactions with Opcache.+I have tested the RFC against opcacheand patched three different Zend Optimizer optimisations which created problems. At the time of writing this, all tests now pass both with Opcache enabled and Opcache disabled.
  
 ==== To Constants === ==== To Constants ===
Line 130: Line 130:
 As this is a language change, the RFC requires a 2/3 majority to pass. As this is a language change, the RFC requires a 2/3 majority to pass.
  
-Voting started on 2016-01-23 and was scheduled to end on 2016-01-31, but was cancelled due to the issue of float handling (see //Open Issues//).+Voting started on 2016-03-20 and ended on 2016-03-28.
  
-<doodle title="Warn about invalid strings in arithmetic" auth="ajf" voteType="single" closed="true">+<doodle title="Accept the ‘Warn about invalid strings in arithmetic’ v1.1 RFC for PHP 7.1?" auth="ajf" voteType="single" closed="true">
    * Yes    * Yes
    * No    * No
 </doodle> </doodle>
 +
 +[[https://wiki.php.net/rfc/invalid_strings_in_arithmetic?rev=1453841945|Voting had previously opened on 2016-01-23]], but it was cancelled due to the //Fractional and scientific notation strings with integer operators// issue.
  
 ===== Patches and Tests ===== ===== Patches and Tests =====
-An incomplete pull request can be found here: https://github.com/php/php-src/pull/1718+A complete pull request for the PHP interpreter, including tests, can be found here: https://github.com/php/php-src/pull/1718 
 + 
 +A complete pull request for the PHP language specification, including tests, can be found here: https://github.com/php/php-langspec/pull/155
  
 ===== Implementation ===== ===== Implementation =====
-After the project is implemented, this section should contain  + 
-  - the version(s) it was merged to +The interpreter patch was merged into 7.1 here: https://github.com/php/php-src/commit/1e82ad8038d3100b7e27be870652c1f639a7200a 
-  a link to the git commit(s) + 
-  a link to the PHP manual entry for the feature+The UPGRADING file notes can be found here (more extensive than in the previously-linked patch), see sections 1 and 2: https://github.com/php/php-src/blob/0105bd20b706c8ab5b0a71f59f11a9dabe735f6b/UPGRADING 
 + 
 +The corresponding mention in the manual can be found here: http://php.net/manual/en/migration71.other-changes.php 
 + 
 +The language specification patch was merged into 7.1 here: https://github.com/php/php-langspec/commit/a3ea4e992f43ea9083c3fe3738a5ded03412f6e1
  
 ===== References ===== ===== References =====
Line 156: Line 164:
 ===== Changelog ===== ===== Changelog =====
  
 +  * v1.1.3 (2016-02-14) - Update for opcache compatibility
 +  * v1.1.2 (2016-02-05) - List more functions affected by support for scientific-notation numeric strings
 +  * v1.1.1 (2016-02-05) - Clarify that handling of scientific-notation numeric strings with <php>intval()</php> only applies for <php>$base</php> = 10, and that it applies to <php>settype()</php>
   * v1.1 (2016-01-26) - Expanded proposal to change handling of fractional and scientific-notation numeric strings with integer operators   * v1.1 (2016-01-26) - Expanded proposal to change handling of fractional and scientific-notation numeric strings with integer operators
   * v1.0 (2016-01-18) - First public version   * v1.0 (2016-01-18) - First public version
rfc/invalid_strings_in_arithmetic.1453843062.txt.gz · Last modified: 2017/09/22 13:28 (external edit)