From f0120ff8787ce5efc509a8365fd815d1144c366e Mon Sep 17 00:00:00 2001 From: Julien Pauli Date: Tue, 29 Mar 2016 18:11:03 +0200 Subject: [PATCH 01/14] 5.5.35 now --- NEWS | 22 +++++++++++++++++++++- configure.in | 2 +- main/php_version.h | 6 +++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 6d3caf60def..8859d6c57cb 100644 --- a/NEWS +++ b/NEWS @@ -2,9 +2,29 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ** PHP 5.5 is in security-only mode , please do not commit to this branch ** -??? 2016, PHP 5.5.34 +??? 2016, PHP 5.5.35 +31 Mar 2016, PHP 5.5.34 +- Fileinfo: + . Fixed bug #71527 (Buffer over-write in finfo_open with malformed magic + file). (Anatol) + +- Mbstring: + . Fixed bug #71906 (AddressSanitizer: negative-size-param (-1) in + mbfl_strcut). (Stas) + +- OBBC + . Fixed bug #71860 (Invalid memory write in phar on filename with \0 in + name). (Stas) + +- SNMP: + . Fixed bug #71704 (php_snmp_error() Format String Vulnerability). + (andrew at jmpesp dot org) + +- Standard + . Fixed bug #71798 (Integer Overflow in php_raw_url_encode). + (taoguangchen at icloud dot com, Stas) 03 Mar 2016, PHP 5.5.33 diff --git a/configure.in b/configure.in index 21a52065c55..c46011a30db 100644 --- a/configure.in +++ b/configure.in @@ -119,7 +119,7 @@ int zend_sprintf(char *buffer, const char *format, ...); PHP_MAJOR_VERSION=5 PHP_MINOR_VERSION=5 -PHP_RELEASE_VERSION=34 +PHP_RELEASE_VERSION=35 PHP_EXTRA_VERSION="-dev" PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION" PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION` diff --git a/main/php_version.h b/main/php_version.h index 25446e3d65e..f87cc38eda9 100644 --- a/main/php_version.h +++ b/main/php_version.h @@ -2,7 +2,7 @@ /* edit configure.in to change version number */ #define PHP_MAJOR_VERSION 5 #define PHP_MINOR_VERSION 5 -#define PHP_RELEASE_VERSION 34 +#define PHP_RELEASE_VERSION 35 #define PHP_EXTRA_VERSION "-dev" -#define PHP_VERSION "5.5.34-dev" -#define PHP_VERSION_ID 50534 +#define PHP_VERSION "5.5.35-dev" +#define PHP_VERSION_ID 50535 From 1e82ad8038d3100b7e27be870652c1f639a7200a Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Wed, 30 Mar 2016 01:44:27 +0100 Subject: [PATCH 02/14] Warn about invalid strings in arithmetic Squashed commit of the following: commit e05d3b67325d4521418483ed924ac9211a188919 Author: Andrea Faulds Date: Wed Mar 30 01:43:35 2016 +0100 UPGRADING and NEWS commit 6caf1d4585207d1b02fb06a216cd7da1a1f5e12d Author: Andrea Faulds Date: Sun Mar 20 21:18:33 2016 +0000 Fixes commit 6dadb1b0efe5e2ed071e95a55c806519e61377ac Author: Andrea Faulds Date: Sun Feb 14 02:15:01 2016 +0000 Add test for numeric string errors in assignment commit bd5f04e8dd576f92a48d25546f4f9a0f57f374de Author: Andrea Faulds Date: Sat Feb 13 23:53:05 2016 +0000 Add test for numeric string errors commit c72e92f16d512bcae30cc9639c89bcb08d971742 Author: Andrea Faulds Date: Tue Jan 26 23:28:33 2016 +0000 Add test for scientific notation in integer operations commit d94c08852d405b3a7ef6c84d24bf7915c890ce78 Author: Andrea Faulds Date: Sun Feb 14 01:25:57 2016 +0000 Disable optimiser evaluation for numeric string errors commit 30ee954ed13d933e766c68605d683c8ebae3d8ee Author: Andrea Faulds Date: Sun Feb 14 01:46:25 2016 +0000 fixup commit a6403b79e054c95e2b7345d787f3092b261eed27 Author: Andrea Faulds Date: Sat Feb 13 22:00:27 2016 +0000 Do not convert error-causing numeric strings ahead-of-time commit f9dc35401471ef3035954cb6f171826769297548 Author: Andrea Faulds Date: Sat Feb 13 19:15:38 2016 +0000 Disable compile-time evaluation for numeric string errors commit e05b0cc8496ea082c6db27efd8b8277ef1f785b5 Author: Andrea Faulds Date: Fri Feb 5 11:42:26 2016 +0000 Make _zval_get_long_func_noisy function for inlining commit 84d66321a57e579759109650c8bb7e3d5002854a Author: Andrea Faulds Date: Tue Jan 26 23:10:00 2016 +0000 Update tests commit 5ac4a0cc4bff282e3a15eaa8ab44b67391881a6d Author: Andrea Faulds Date: Tue Jan 26 22:08:19 2016 +0000 Use is_numeric_string_ex for zval_get_long etc. commit c21f08848533723331012a62a153de3577731d6a Author: Andrea Faulds Date: Thu Jan 7 21:13:04 2016 +0000 Update tests commit 63e214cf8160420bfc51c6a2b4ae32f09ad8e8af Author: Andrea Faulds Date: Wed Jan 6 00:28:01 2016 +0000 Warn on non-/bad numeric strings in arithmetic --- NEWS | 5 + UPGRADING | 8 + Zend/tests/add_006.phpt | 8 + Zend/tests/add_007.phpt | 5 + Zend/tests/constant_expressions_dynamic.phpt | 4 +- Zend/tests/int_conversion_exponents.phpt | 52 ++++ Zend/tests/numeric_string_errors.phpt | 195 +++++++++++++++ Zend/tests/numeric_string_errors_assign.phpt | 236 ++++++++++++++++++ Zend/tests/self_and.phpt | 4 + Zend/tests/self_mod.phpt | 4 + Zend/tests/self_or.phpt | 4 + Zend/tests/self_xor.phpt | 4 + Zend/tests/shift_001.phpt | 4 + Zend/tests/shift_002.phpt | 4 + Zend/zend_API.c | 12 +- Zend/zend_compile.c | 51 +++- Zend/zend_compile.h | 2 + Zend/zend_operators.c | 104 +++++--- Zend/zend_operators.h | 10 + ext/opcache/Optimizer/block_pass.c | 5 + ext/opcache/Optimizer/pass1_5.c | 3 + ext/opcache/Optimizer/pass2.c | 22 +- .../file/file_put_contents_variation7.phpt | 6 +- .../tests/general_functions/floatval.phpt | 4 + .../floatval_variation1.phpt | 7 +- .../gettype_settype_variation2.phpt | 16 +- ext/standard/tests/math/decbin_basic.phpt | 2 +- ext/standard/tests/math/dechex_basic.phpt | 2 +- ext/standard/tests/math/decoct_basic.phpt | 2 +- ext/standard/tests/math/pow_variation1.phpt | 10 + .../tests/math/pow_variation1_64bit.phpt | 10 + ext/standard/tests/math/pow_variation2.phpt | 10 + ext/standard/tests/strings/bug55871.phpt | 2 + ext/standard/type.c | 2 +- tests/lang/bug28800.phpt | 24 +- .../bitwiseShiftLeft_variationStr_64bit.phpt | 20 +- .../bitwiseShiftRight_variationStr.phpt | 20 +- .../lang/operators/modulus_variationStr.phpt | 28 +-- tests/lang/operators/negate_variationStr.phpt | 18 +- 39 files changed, 821 insertions(+), 108 deletions(-) create mode 100644 Zend/tests/int_conversion_exponents.phpt create mode 100644 Zend/tests/numeric_string_errors.phpt create mode 100644 Zend/tests/numeric_string_errors_assign.phpt diff --git a/NEWS b/NEWS index f677f0a0d37..af7a2afe12c 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,11 @@ PHP NEWS . Added support for negative string offsets in string offset syntax and various string functions. (Francois) . Added a form of the list() construct where keys can be specified. (Andrea) + . Number operators taking numeric strings now emit E_NOTICEs or E_WARNINGs + when given malformed numeric strings. (Andrea) + . (int), intval() where $base is 10 or unspecified, settype(), integer + operators and other conversions now always respect scientific notation in + numeric strings. (Andrea) - FTP: . Implemented FR #55651 (Option to ignore the returned FTP PASV address). diff --git a/UPGRADING b/UPGRADING index a938978d7bf..bda00da7db7 100644 --- a/UPGRADING +++ b/UPGRADING @@ -21,6 +21,10 @@ PHP 7.1 UPGRADE NOTES - Core: . 'void' can no longer be used as the name of a class, interface, or trait. This applies to declarations, class_alias() and use statements. + . (int), intval() where $base is 10 or unspecified, settype(), integer + operators and other conversions now always respect scientific notation in + numeric strings. + (RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic) - JSON: . When calling json_encode with JSON_UNESCAPED_UNICODE option, U+2028 and @@ -37,6 +41,10 @@ PHP 7.1 UPGRADE NOTES (RFC: https://wiki.php.net/rfc/negative-string-offsets) . Added a form of the list() construct where keys can be specified. (RFC: https://wiki.php.net/rfc/list_keys) + . Number operators taking numeric strings now emit "A non well formed numeric + string encountered" E_NOTICEs for leading-numeric strings, and "A + non-numeric string encountered" E_WARNINGs for non-numeric strings. + (RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic) ======================================== 3. Changes in SAPI modules diff --git a/Zend/tests/add_006.phpt b/Zend/tests/add_006.phpt index d56df2f329c..fe1c0830e25 100644 --- a/Zend/tests/add_006.phpt +++ b/Zend/tests/add_006.phpt @@ -38,11 +38,19 @@ var_dump($c); echo "Done\n"; ?> --EXPECTF-- + +Warning: A non-numeric value encountered in %s on line %d int(75636) + +Notice: A non well formed numeric value encountered in %s on line %d int(951858) int(48550510) float(75661.68) + +Warning: A non-numeric value encountered in %s on line %d int(75636) + +Notice: A non well formed numeric value encountered in %s on line %d int(951858) int(48550510) float(75661.68) diff --git a/Zend/tests/add_007.phpt b/Zend/tests/add_007.phpt index 66f54057060..089b24ae0b5 100644 --- a/Zend/tests/add_007.phpt +++ b/Zend/tests/add_007.phpt @@ -19,8 +19,13 @@ var_dump($c); echo "Done\n"; ?> --EXPECTF-- + +Warning: A non-numeric value encountered in %s on line %d + Exception: Unsupported operand types +Warning: A non-numeric value encountered in %s on line %d + Fatal error: Uncaught Error: Unsupported operand types in %s:%d Stack trace: #0 {main} diff --git a/Zend/tests/constant_expressions_dynamic.phpt b/Zend/tests/constant_expressions_dynamic.phpt index d4e06ee258b..b0ba3a5b194 100644 --- a/Zend/tests/constant_expressions_dynamic.phpt +++ b/Zend/tests/constant_expressions_dynamic.phpt @@ -42,7 +42,9 @@ var_dump( ); ?> ---EXPECT-- +--EXPECTF-- + +Warning: A non-numeric value encountered in %s on line %d int(3) string(4) "1foo" bool(false) diff --git a/Zend/tests/int_conversion_exponents.phpt b/Zend/tests/int_conversion_exponents.phpt new file mode 100644 index 00000000000..d924cb7b81e --- /dev/null +++ b/Zend/tests/int_conversion_exponents.phpt @@ -0,0 +1,52 @@ +--TEST-- +Integer conversion from scientific notation +--FILE-- + +--EXPECTF-- +int(1234500000) +int(-1234500000) +int(1234500000) +int(-1234500000) +int(1234500000) +int(-1234500000) +int(1234500000) +int(-1234500000) + +int(1234500000) +int(-1234500000) +int(1234500000) +int(-1234500000) + +Notice: A non well formed numeric value encountered in %s on line %d +int(1234500000) + +Notice: A non well formed numeric value encountered in %s on line %d +int(-1234500000) + +Notice: A non well formed numeric value encountered in %s on line %d +int(1234500000) + +Notice: A non well formed numeric value encountered in %s on line %d +int(-1234500000) diff --git a/Zend/tests/numeric_string_errors.phpt b/Zend/tests/numeric_string_errors.phpt new file mode 100644 index 00000000000..26ceea7dee7 --- /dev/null +++ b/Zend/tests/numeric_string_errors.phpt @@ -0,0 +1,195 @@ +--TEST-- +Invalid numeric string E_WARNINGs and E_NOTICEs +--FILE-- +> "53 ullamco"); +var_dump("laboris" >> "nisi"); +echo "---", PHP_EOL; +var_dump("59 ut" | 61); +var_dump(67 | "71 aliquip"); +var_dump("ex" | 73); +var_dump(79 | "ea"); +echo "---", PHP_EOL; +var_dump("83 commodo" & 89); +var_dump(97 & "101 consequat."); +var_dump("Duis" & 103); +var_dump(107 & "aute"); +echo "---", PHP_EOL; +var_dump("109 irure" ^ 113); +var_dump(127 ^ "131 dolor"); +var_dump("in" ^ 137); +var_dump(139 ^ "reprehenderit"); +echo "---", PHP_EOL; +var_dump(+"149 in"); +var_dump(+"voluptate"); +echo "---", PHP_EOL; +var_dump(-"151 velit"); +var_dump(-"esse"); +?> +--EXPECTF-- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(5) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(-2) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(143) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +float(0.89473684210526) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d + +Warning: Division by zero in %s on line %d +float(NAN) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +float(3.0910586430935E+39) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(1) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(31) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(360639813910528) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(0) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(63) + +Notice: A non well formed numeric value encountered in %s on line %d +int(71) + +Warning: A non-numeric value encountered in %s on line %d +int(73) + +Warning: A non-numeric value encountered in %s on line %d +int(79) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(81) + +Notice: A non well formed numeric value encountered in %s on line %d +int(97) + +Warning: A non-numeric value encountered in %s on line %d +int(0) + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(28) + +Notice: A non well formed numeric value encountered in %s on line %d +int(252) + +Warning: A non-numeric value encountered in %s on line %d +int(137) + +Warning: A non-numeric value encountered in %s on line %d +int(139) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(149) + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(-151) + +Warning: A non-numeric value encountered in %s on line %d +int(0) diff --git a/Zend/tests/numeric_string_errors_assign.phpt b/Zend/tests/numeric_string_errors_assign.phpt new file mode 100644 index 00000000000..7fb8898fc99 --- /dev/null +++ b/Zend/tests/numeric_string_errors_assign.phpt @@ -0,0 +1,236 @@ +--TEST-- +Invalid numeric string E_WARNINGs and E_NOTICEs, combined assignment operations +--FILE-- +>= "53 ullamco"; +var_dump($a); +$a = foxcache("laboris"); +$a >>= "nisi"; +var_dump($a); +echo "---", PHP_EOL; +$a = foxcache("59 ut"); +$a |= 61; +var_dump($a); +$a = foxcache(67); +$a |= "71 aliquip"; +var_dump($a); +$a = foxcache("ex"); +$a |= 73; +var_dump($a); +$a = foxcache(79); +$a |= "ea"; +var_dump($a); +echo "---", PHP_EOL; +$a = foxcache("83 commodo"); +$a &= 89; +var_dump($a); +$a = foxcache(97); +$a &= "101 consequat."; +var_dump($a); +$a = foxcache("Duis"); +$a &= 103; +var_dump($a); +$a = foxcache(107); +$a &= "aute"; +var_dump($a); +echo "---", PHP_EOL; +$a = foxcache("109 irure"); +$a ^= 113; +var_dump($a); +$a = foxcache(127); +$a ^= "131 dolor"; +var_dump($a); +$a = foxcache("in"); +$a ^= 137; +var_dump($a); +$a = foxcache(139); +$a ^= "reprehenderit"; +var_dump($a); +?> +--EXPECTF-- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(5) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(-2) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(143) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +float(0.89473684210526) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d + +Warning: Division by zero in %s on line %d +float(NAN) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +float(3.0910586430935E+39) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(1) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(31) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(360639813910528) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d +int(0) + +Warning: A non-numeric value encountered in %s on line %d + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(63) + +Notice: A non well formed numeric value encountered in %s on line %d +int(71) + +Warning: A non-numeric value encountered in %s on line %d +int(73) + +Warning: A non-numeric value encountered in %s on line %d +int(79) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(81) + +Notice: A non well formed numeric value encountered in %s on line %d +int(97) + +Warning: A non-numeric value encountered in %s on line %d +int(0) + +Warning: A non-numeric value encountered in %s on line %d +int(0) +--- + +Notice: A non well formed numeric value encountered in %s on line %d +int(28) + +Notice: A non well formed numeric value encountered in %s on line %d +int(252) + +Warning: A non-numeric value encountered in %s on line %d +int(137) + +Warning: A non-numeric value encountered in %s on line %d +int(139) diff --git a/Zend/tests/self_and.phpt b/Zend/tests/self_and.phpt index cdcde77992b..44db877e929 100644 --- a/Zend/tests/self_and.phpt +++ b/Zend/tests/self_and.phpt @@ -20,6 +20,10 @@ echo "Done\n"; ?> --EXPECTF-- int(18) + +Warning: A non-numeric value encountered in %s on line %d int(0) + +Notice: A non well formed numeric value encountered in %s on line %d int(33) Done diff --git a/Zend/tests/self_mod.phpt b/Zend/tests/self_mod.phpt index 19e45d88fc4..0b10987aeb8 100644 --- a/Zend/tests/self_mod.phpt +++ b/Zend/tests/self_mod.phpt @@ -20,6 +20,10 @@ echo "Done\n"; ?> --EXPECTF-- int(13) + +Warning: A non-numeric value encountered in %s on line %d int(0) + +Notice: A non well formed numeric value encountered in %s on line %d int(3) Done diff --git a/Zend/tests/self_or.phpt b/Zend/tests/self_or.phpt index ae667bff16a..8ace518bde5 100644 --- a/Zend/tests/self_or.phpt +++ b/Zend/tests/self_or.phpt @@ -20,6 +20,10 @@ echo "Done\n"; ?> --EXPECTF-- int(127) + +Warning: A non-numeric value encountered in %s on line %d int(11) + +Notice: A non well formed numeric value encountered in %s on line %d int(45345) Done diff --git a/Zend/tests/self_xor.phpt b/Zend/tests/self_xor.phpt index a7e43f539d6..c097930d6dd 100644 --- a/Zend/tests/self_xor.phpt +++ b/Zend/tests/self_xor.phpt @@ -20,6 +20,10 @@ echo "Done\n"; ?> --EXPECTF-- int(109) + +Warning: A non-numeric value encountered in %s on line %d int(11) + +Notice: A non well formed numeric value encountered in %s on line %d int(45312) Done diff --git a/Zend/tests/shift_001.phpt b/Zend/tests/shift_001.phpt index aeb399452d5..7546f1a6d8f 100644 --- a/Zend/tests/shift_001.phpt +++ b/Zend/tests/shift_001.phpt @@ -20,6 +20,10 @@ echo "Done\n"; ?> --EXPECTF-- int(492) + +Warning: A non-numeric value encountered in %s on line %d int(0) + +Notice: A non well formed numeric value encountered in %s on line %d int(362760) Done diff --git a/Zend/tests/shift_002.phpt b/Zend/tests/shift_002.phpt index 4d8421a5666..6288152585f 100644 --- a/Zend/tests/shift_002.phpt +++ b/Zend/tests/shift_002.phpt @@ -20,6 +20,10 @@ echo "Done\n"; ?> --EXPECTF-- int(30) + +Warning: A non-numeric value encountered in %s on line %d int(0) + +Notice: A non well formed numeric value encountered in %s on line %d int(5668) Done diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5ebfe2cb178..18e6e0f4f4a 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -370,11 +370,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de if (UNEXPECTED(zend_isnan(Z_DVAL_P(arg)))) { return 0; } - if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(Z_DVAL_P(arg)))) { - *dest = (Z_DVAL_P(arg) > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN; - } else { - *dest = zend_dval_to_lval(Z_DVAL_P(arg)); - } + *dest = zend_dval_to_lval_cap(Z_DVAL_P(arg)); } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { double d; int type; @@ -384,11 +380,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_long_cap_weak(zval *arg, zend_long *de if (UNEXPECTED(zend_isnan(d))) { return 0; } - if (UNEXPECTED(!ZEND_DOUBLE_FITS_LONG(d))) { - *dest = (d > 0) ? ZEND_LONG_MAX : ZEND_LONG_MIN; - } else { - *dest = zend_dval_to_lval(d); - } + *dest = zend_dval_to_lval_cap(d); } else { return 0; } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2e1ce9ba448..1401a6e051a 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6237,6 +6237,35 @@ static zend_bool zend_try_ct_eval_magic_const(zval *zv, zend_ast *ast) /* {{{ */ } /* }}} */ +ZEND_API zend_bool zend_binary_op_produces_numeric_string_error(uint32_t opcode, zval *op1, zval *op2) /* {{{ */ +{ + if (!(opcode == ZEND_ADD || opcode == ZEND_SUB || opcode == ZEND_MUL || opcode == ZEND_DIV + || opcode == ZEND_POW || opcode == ZEND_MOD || opcode == ZEND_SL || opcode == ZEND_SR + || opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR)) { + return 0; + } + + /* While basic arithmetic operators always produce numeric string errors, + * bitwise operators don't produce errors if both operands are strings */ + if ((opcode == ZEND_BW_OR || opcode == ZEND_BW_AND || opcode == ZEND_BW_XOR) + && Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) { + return 0; + } + + if (Z_TYPE_P(op1) == IS_STRING + && !is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), NULL, NULL, 0)) { + return 1; + } + + if (Z_TYPE_P(op2) == IS_STRING + && !is_numeric_string(Z_STRVAL_P(op2), Z_STRLEN_P(op2), NULL, NULL, 0)) { + return 1; + } + + return 0; +} +/* }}} */ + static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode, zval *op1, zval *op2) /* {{{ */ { binary_op_type fn = get_binary_op(opcode); @@ -6250,6 +6279,11 @@ static inline zend_bool zend_try_ct_eval_binary_op(zval *result, uint32_t opcode return 0; } + /* don't evaluate numeric string error-producing operations at compile-time */ + if (zend_binary_op_produces_numeric_string_error(opcode, op1, op2)) { + return 0; + } + fn(result, op1, op2); return 1; } @@ -6262,11 +6296,11 @@ static inline void zend_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op } /* }}} */ -static inline void zend_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */ +static inline zend_bool zend_try_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */ { zval left; ZVAL_LONG(&left, (kind == ZEND_AST_UNARY_PLUS) ? 1 : -1); - mul_function(result, &left, op); + return zend_try_ct_eval_binary_op(result, ZEND_MUL, &left, op); } /* }}} */ @@ -6464,10 +6498,11 @@ void zend_compile_unary_pm(znode *result, zend_ast *ast) /* {{{ */ zend_compile_expr(&expr_node, expr_ast); if (expr_node.op_type == IS_CONST) { - result->op_type = IS_CONST; - zend_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant); - zval_ptr_dtor(&expr_node.u.constant); - return; + if (zend_try_ct_eval_unary_pm(&result->u.constant, ast->kind, &expr_node.u.constant)) { + result->op_type = IS_CONST; + zval_ptr_dtor(&expr_node.u.constant); + return; + } } lefthand_node.op_type = IS_CONST; @@ -7802,7 +7837,9 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ return; } - zend_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0])); + if (!zend_try_ct_eval_unary_pm(&result, ast->kind, zend_ast_get_zval(ast->child[0]))) { + return; + } break; case ZEND_AST_CONDITIONAL: { diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index f3dc8081b8a..b3ba352df88 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -1023,6 +1023,8 @@ END_EXTERN_C() /* The default value for CG(compiler_options) during eval() */ #define ZEND_COMPILE_DEFAULT_FOR_EVAL 0 +ZEND_API zend_bool zend_binary_op_produces_numeric_string_error(uint32_t opcode, zval *op1, zval *op2); + #endif /* ZEND_COMPILE_H */ /* diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 50557e56d80..1710ba44dd1 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -147,7 +147,7 @@ static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */ } /* }}} */ -ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ +void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent) /* {{{ */ { try_again: switch (Z_TYPE_P(op)) { @@ -159,8 +159,11 @@ try_again: zend_string *str; str = Z_STR_P(op); - if ((Z_TYPE_INFO_P(op)=is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &Z_LVAL_P(op), &Z_DVAL_P(op), 1)) == 0) { + if ((Z_TYPE_INFO_P(op)=is_numeric_string(ZSTR_VAL(str), ZSTR_LEN(str), &Z_LVAL_P(op), &Z_DVAL_P(op), silent ? 1 : -1)) == 0) { ZVAL_LONG(op, 0); + if (!silent) { + zend_error(E_WARNING, "A non-numeric value encountered"); + } } zend_string_release(str); break; @@ -186,18 +189,27 @@ try_again: } /* }}} */ +ZEND_API void ZEND_FASTCALL convert_scalar_to_number(zval *op) /* {{{ */ +{ + _convert_scalar_to_number(op, 1); +} +/* }}} */ + /* {{{ zendi_convert_scalar_to_number */ -#define zendi_convert_scalar_to_number(op, holder, result) \ +#define zendi_convert_scalar_to_number(op, holder, result, silent) \ if (op==result) { \ if (Z_TYPE_P(op) != IS_LONG) { \ - convert_scalar_to_number(op); \ + _convert_scalar_to_number(op, silent); \ } \ } else { \ switch (Z_TYPE_P(op)) { \ case IS_STRING: \ { \ - if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), 1)) == 0) { \ + if ((Z_TYPE_INFO(holder)=is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &Z_LVAL(holder), &Z_DVAL(holder), silent ? 1 : -1)) == 0) { \ ZVAL_LONG(&(holder), 0); \ + if (!silent) { \ + zend_error(E_WARNING, "A non-numeric value encountered"); \ + } \ } \ (op) = &(holder); \ break; \ @@ -258,7 +270,7 @@ try_again: } \ } \ ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(op, op_func); \ - op1_lval = _zval_get_long_func(op1); \ + op1_lval = _zval_get_long_func_noisy(op1); \ } else { \ op1_lval = Z_LVAL_P(op1); \ } \ @@ -273,7 +285,7 @@ try_again: } \ } \ ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(op); \ - op2_lval = _zval_get_long_func(op2); \ + op2_lval = _zval_get_long_func_noisy(op2); \ } else { \ op2_lval = Z_LVAL_P(op2); \ } \ @@ -313,8 +325,11 @@ try_again: case IS_STRING: { zend_string *str = Z_STR_P(op); - - ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base)); + if (base == 10) { + ZVAL_LONG(op, zval_get_long(op)); + } else { + ZVAL_LONG(op, ZEND_STRTOL(ZSTR_VAL(str), NULL, base)); + } zend_string_release(str); } break; @@ -728,7 +743,7 @@ ZEND_API void multi_convert_to_string_ex(int argc, ...) /* {{{ */ } /* }}} */ -ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */ +static zend_always_inline zend_long ZEND_FASTCALL _zval_get_long_func_ex(zval *op, zend_bool silent) /* {{{ */ { try_again: switch (Z_TYPE_P(op)) { @@ -744,7 +759,26 @@ try_again: case IS_DOUBLE: return zend_dval_to_lval(Z_DVAL_P(op)); case IS_STRING: - return ZEND_STRTOL(Z_STRVAL_P(op), NULL, 10); + { + zend_uchar type; + zend_long lval; + double dval; + if (0 == (type = is_numeric_string(Z_STRVAL_P(op), Z_STRLEN_P(op), &lval, &dval, silent ? 1 : -1))) { + if (!silent) { + zend_error(E_WARNING, "A non-numeric value encountered"); + } + return 0; + } else if (EXPECTED(type == IS_LONG)) { + return lval; + } else { + /* Previously we used strtol here, not is_numeric_string, + * and strtol gives you LONG_MAX/_MIN on overflow. + * We use use saturating conversion to emulate strtol()'s + * behaviour. + */ + return zend_dval_to_lval_cap(dval); + } + } case IS_ARRAY: return zend_hash_num_elements(Z_ARRVAL_P(op)) ? 1 : 0; case IS_OBJECT: @@ -766,6 +800,18 @@ try_again: } /* }}} */ +ZEND_API zend_long ZEND_FASTCALL _zval_get_long_func(zval *op) /* {{{ */ +{ + return _zval_get_long_func_ex(op, 1); +} +/* }}} */ + +static zend_long ZEND_FASTCALL _zval_get_long_func_noisy(zval *op) /* {{{ */ +{ + return _zval_get_long_func_ex(op, 0); +} +/* }}} */ + ZEND_API double ZEND_FASTCALL _zval_get_double_func(zval *op) /* {{{ */ { try_again: @@ -916,8 +962,8 @@ ZEND_API int ZEND_FASTCALL add_function(zval *result, zval *op1, zval *op2) /* { } else if (!converted) { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_ADD, add_function); - zendi_convert_scalar_to_number(op1, op1_copy, result); - zendi_convert_scalar_to_number(op2, op2_copy, result); + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { zend_throw_error(NULL, "Unsupported operand types"); @@ -969,8 +1015,8 @@ ZEND_API int ZEND_FASTCALL sub_function(zval *result, zval *op1, zval *op2) /* { } else if (!converted) { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_SUB, sub_function); - zendi_convert_scalar_to_number(op1, op1_copy, result); - zendi_convert_scalar_to_number(op2, op2_copy, result); + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { zend_throw_error(NULL, "Unsupported operand types"); @@ -1016,8 +1062,8 @@ ZEND_API int ZEND_FASTCALL mul_function(zval *result, zval *op1, zval *op2) /* { } else if (!converted) { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_MUL, mul_function); - zendi_convert_scalar_to_number(op1, op1_copy, result); - zendi_convert_scalar_to_number(op2, op2_copy, result); + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { zend_throw_error(NULL, "Unsupported operand types"); @@ -1098,13 +1144,13 @@ ZEND_API int ZEND_FASTCALL pow_function(zval *result, zval *op1, zval *op2) /* { ZVAL_LONG(result, 0); return SUCCESS; } else { - zendi_convert_scalar_to_number(op1, op1_copy, result); + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); } if (Z_TYPE_P(op2) == IS_ARRAY) { ZVAL_LONG(result, 1L); return SUCCESS; } else { - zendi_convert_scalar_to_number(op2, op2_copy, result); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); } converted = 1; } else { @@ -1169,8 +1215,8 @@ ZEND_API int ZEND_FASTCALL div_function(zval *result, zval *op1, zval *op2) /* { } else if (!converted) { ZEND_TRY_BINARY_OBJECT_OPERATION(ZEND_DIV, div_function); - zendi_convert_scalar_to_number(op1, op1_copy, result); - zendi_convert_scalar_to_number(op2, op2_copy, result); + zendi_convert_scalar_to_number(op1, op1_copy, result, 0); + zendi_convert_scalar_to_number(op2, op2_copy, result, 0); converted = 1; } else { zend_throw_error(NULL, "Unsupported operand types"); @@ -1377,13 +1423,13 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_OR, bitwise_or_function); - op1_lval = _zval_get_long_func(op1); + op1_lval = _zval_get_long_func_noisy(op1); } else { op1_lval = Z_LVAL_P(op1); } if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_OR); - op2_lval = _zval_get_long_func(op2); + op2_lval = _zval_get_long_func_noisy(op2); } else { op2_lval = Z_LVAL_P(op2); } @@ -1444,13 +1490,13 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function); - op1_lval = _zval_get_long_func(op1); + op1_lval = _zval_get_long_func_noisy(op1); } else { op1_lval = Z_LVAL_P(op1); } if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_AND); - op2_lval = _zval_get_long_func(op2); + op2_lval = _zval_get_long_func_noisy(op2); } else { op2_lval = Z_LVAL_P(op2); } @@ -1511,13 +1557,13 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) { ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function); - op1_lval = _zval_get_long_func(op1); + op1_lval = _zval_get_long_func_noisy(op1); } else { op1_lval = Z_LVAL_P(op1); } if (UNEXPECTED(Z_TYPE_P(op2) != IS_LONG)) { ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BW_XOR); - op2_lval = _zval_get_long_func(op2); + op2_lval = _zval_get_long_func_noisy(op2); } else { op2_lval = Z_LVAL_P(op2); } @@ -1944,8 +1990,8 @@ ZEND_API int ZEND_FASTCALL compare_function(zval *result, zval *op1, zval *op2) ZVAL_LONG(result, zval_is_true(op1) ? 0 : -1); return SUCCESS; } else { - zendi_convert_scalar_to_number(op1, op1_copy, result); - zendi_convert_scalar_to_number(op2, op2_copy, result); + zendi_convert_scalar_to_number(op1, op1_copy, result, 1); + zendi_convert_scalar_to_number(op2, op2_copy, result, 1); converted = 1; } } else if (Z_TYPE_P(op1)==IS_ARRAY) { diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index b0b167bd747..db6162a4e52 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -122,6 +122,16 @@ static zend_always_inline zend_long zend_dval_to_lval(double d) return (zend_long)d; } #endif + +static zend_always_inline zend_long zend_dval_to_lval_cap(double d) +{ + if (UNEXPECTED(!zend_finite(d)) || UNEXPECTED(zend_isnan(d))) { + return 0; + } else if (!ZEND_DOUBLE_FITS_LONG(d)) { + return (d > 0 ? ZEND_LONG_MAX : ZEND_LONG_MIN); + } + return (zend_long)d; +} /* }}} */ #define ZEND_IS_DIGIT(c) ((c) >= '0' && (c) <= '9') diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 52a440fba07..0ecb57e2b90 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -683,9 +683,14 @@ optimize_constant_binary_op: } else if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) && zval_get_long(&ZEND_OP2_LITERAL(opline)) < 0) { SET_VAR_SOURCE(opline); + opline++; + continue; + } else if (zend_binary_op_produces_numeric_string_error(opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline))) { + SET_VAR_SOURCE(opline); opline++; continue; } + printf("%d\n", opline->opcode); er = EG(error_reporting); EG(error_reporting) = 0; if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) { diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c index ae31504f4c0..71f879e958a 100644 --- a/ext/opcache/Optimizer/pass1_5.c +++ b/ext/opcache/Optimizer/pass1_5.c @@ -84,6 +84,9 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) zval_get_long(&ZEND_OP2_LITERAL(opline)) < 0) { /* shift by negative number */ break; + } else if (zend_binary_op_produces_numeric_string_error(opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline))) { + /* produces numeric string E_NOTICE/E_WARNING */ + break; } er = EG(error_reporting); EG(error_reporting) = 0; diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c index d2a2064a787..2be97ed9382 100644 --- a/ext/opcache/Optimizer/pass2.c +++ b/ext/opcache/Optimizer/pass2.c @@ -48,7 +48,10 @@ void zend_optimizer_pass2(zend_op_array *op_array) case ZEND_POW: if (ZEND_OP1_TYPE(opline) == IS_CONST) { if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) { - convert_scalar_to_number(&ZEND_OP1_LITERAL(opline)); + /* don't optimise if it should produce a runtime numeric string error */ + if (is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0)) { + convert_scalar_to_number(&ZEND_OP1_LITERAL(opline)); + } } } /* break missing *intentionally* - the assign_op's may only optimize op2 */ @@ -63,7 +66,10 @@ void zend_optimizer_pass2(zend_op_array *op_array) } if (ZEND_OP2_TYPE(opline) == IS_CONST) { if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) { - convert_scalar_to_number(&ZEND_OP2_LITERAL(opline)); + /* don't optimise if it should produce a runtime numeric string error */ + if (is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0)) { + convert_scalar_to_number(&ZEND_OP2_LITERAL(opline)); + } } } break; @@ -73,7 +79,11 @@ void zend_optimizer_pass2(zend_op_array *op_array) case ZEND_SR: if (ZEND_OP1_TYPE(opline) == IS_CONST) { if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_LONG) { - convert_to_long(&ZEND_OP1_LITERAL(opline)); + /* don't optimise if it should produce a runtime numeric string error */ + if (!(Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING + && !is_numeric_string(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), NULL, NULL, 0))) { + convert_to_long(&ZEND_OP1_LITERAL(opline)); + } } } /* break missing *intentionally - the assign_op's may only optimize op2 */ @@ -86,7 +96,11 @@ void zend_optimizer_pass2(zend_op_array *op_array) } if (ZEND_OP2_TYPE(opline) == IS_CONST) { if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) { - convert_to_long(&ZEND_OP2_LITERAL(opline)); + /* don't optimise if it should produce a runtime numeric string error */ + if (!(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING + && !is_numeric_string(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), NULL, NULL, 0))) { + convert_to_long(&ZEND_OP2_LITERAL(opline)); + } } } break; diff --git a/ext/standard/tests/file/file_put_contents_variation7.phpt b/ext/standard/tests/file/file_put_contents_variation7.phpt index 5c8e5f36023..b1b2face607 100644 --- a/ext/standard/tests/file/file_put_contents_variation7.phpt +++ b/ext/standard/tests/file/file_put_contents_variation7.phpt @@ -51,10 +51,10 @@ for($i = 0; $i $type ) { ?> ===DONE=== --EXPECTF-- + +Notice: A non well formed numeric value encountered in %s on line %d + +Notice: A non well formed numeric value encountered in %s on line %d + *** Testing floatval() on non floating types *** -- Iteration : -2147483648 -- @@ -151,4 +156,4 @@ float(0) -- Iteration : null -- float(0) -===DONE=== \ No newline at end of file +===DONE=== diff --git a/ext/standard/tests/general_functions/gettype_settype_variation2.phpt b/ext/standard/tests/general_functions/gettype_settype_variation2.phpt index 2242952769c..18b05b6a972 100644 --- a/ext/standard/tests/general_functions/gettype_settype_variation2.phpt +++ b/ext/standard/tests/general_functions/gettype_settype_variation2.phpt @@ -282,7 +282,7 @@ string(7) "integer" -- Iteration 18 -- string(6) "string" bool(true) -int(1) +int(100) string(7) "integer" -- Iteration 19 -- string(6) "string" @@ -297,7 +297,7 @@ string(7) "integer" -- Iteration 21 -- string(6) "string" bool(true) -int(-1) +int(0) string(7) "integer" -- Iteration 22 -- string(6) "string" @@ -312,7 +312,7 @@ string(7) "integer" -- Iteration 24 -- string(6) "string" bool(true) -int(1) +int(100) string(7) "integer" -- Iteration 25 -- string(6) "string" @@ -327,7 +327,7 @@ string(7) "integer" -- Iteration 27 -- string(6) "string" bool(true) -int(-1) +int(0) string(7) "integer" -- Iteration 28 -- string(6) "string" @@ -687,7 +687,7 @@ string(7) "integer" -- Iteration 18 -- string(6) "string" bool(true) -int(1) +int(100) string(7) "integer" -- Iteration 19 -- string(6) "string" @@ -702,7 +702,7 @@ string(7) "integer" -- Iteration 21 -- string(6) "string" bool(true) -int(-1) +int(0) string(7) "integer" -- Iteration 22 -- string(6) "string" @@ -717,7 +717,7 @@ string(7) "integer" -- Iteration 24 -- string(6) "string" bool(true) -int(1) +int(100) string(7) "integer" -- Iteration 25 -- string(6) "string" @@ -732,7 +732,7 @@ string(7) "integer" -- Iteration 27 -- string(6) "string" bool(true) -int(-1) +int(0) string(7) "integer" -- Iteration 28 -- string(6) "string" diff --git a/ext/standard/tests/math/decbin_basic.phpt b/ext/standard/tests/math/decbin_basic.phpt index b4389956f42..572a04245e9 100644 --- a/ext/standard/tests/math/decbin_basic.phpt +++ b/ext/standard/tests/math/decbin_basic.phpt @@ -31,7 +31,7 @@ string(2) "11" string(7) "1011111" string(4) "1010" string(12) "111101101110" -string(2) "11" +string(12) "111101101110" string(6) "100111" string(1) "0" string(1) "1" diff --git a/ext/standard/tests/math/dechex_basic.phpt b/ext/standard/tests/math/dechex_basic.phpt index 2423d8e748f..ac53a97b34f 100644 --- a/ext/standard/tests/math/dechex_basic.phpt +++ b/ext/standard/tests/math/dechex_basic.phpt @@ -30,7 +30,7 @@ string(1) "3" string(2) "5f" string(1) "a" string(3) "f6e" -string(1) "3" +string(3) "f6e" string(2) "27" string(1) "0" string(1) "1" diff --git a/ext/standard/tests/math/decoct_basic.phpt b/ext/standard/tests/math/decoct_basic.phpt index cc1f0a899ac..3a5011b973e 100644 --- a/ext/standard/tests/math/decoct_basic.phpt +++ b/ext/standard/tests/math/decoct_basic.phpt @@ -30,7 +30,7 @@ string(1) "3" string(3) "137" string(2) "12" string(4) "7556" -string(1) "3" +string(4) "7556" string(2) "47" string(1) "0" string(1) "1" diff --git a/ext/standard/tests/math/pow_variation1.phpt b/ext/standard/tests/math/pow_variation1.phpt index 5576e5b4933..c744c4eb9d4 100644 --- a/ext/standard/tests/math/pow_variation1.phpt +++ b/ext/standard/tests/math/pow_variation1.phpt @@ -143,21 +143,31 @@ int(1) int(0) -- Iteration 17 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 18 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 19 -- int(0) -- Iteration 20 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 21 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 22 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 23 -- diff --git a/ext/standard/tests/math/pow_variation1_64bit.phpt b/ext/standard/tests/math/pow_variation1_64bit.phpt index e1986ba8582..ea2ae45d18a 100644 --- a/ext/standard/tests/math/pow_variation1_64bit.phpt +++ b/ext/standard/tests/math/pow_variation1_64bit.phpt @@ -143,21 +143,31 @@ int(1) int(0) -- Iteration 17 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 18 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 19 -- int(0) -- Iteration 20 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 21 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 22 -- + +Warning: A non-numeric value encountered in %s on line %d int(0) -- Iteration 23 -- diff --git a/ext/standard/tests/math/pow_variation2.phpt b/ext/standard/tests/math/pow_variation2.phpt index f571936727a..36b085b6474 100644 --- a/ext/standard/tests/math/pow_variation2.phpt +++ b/ext/standard/tests/math/pow_variation2.phpt @@ -139,21 +139,31 @@ float(20.3) float(1) -- Iteration 17 -- + +Warning: A non-numeric value encountered in %s on line %d float(1) -- Iteration 18 -- + +Warning: A non-numeric value encountered in %s on line %d float(1) -- Iteration 19 -- int(1) -- Iteration 20 -- + +Warning: A non-numeric value encountered in %s on line %d float(1) -- Iteration 21 -- + +Warning: A non-numeric value encountered in %s on line %d float(1) -- Iteration 22 -- + +Warning: A non-numeric value encountered in %s on line %d float(1) -- Iteration 23 -- diff --git a/ext/standard/tests/strings/bug55871.phpt b/ext/standard/tests/strings/bug55871.phpt index 249d1bd3a32..0044f50ce70 100644 --- a/ext/standard/tests/strings/bug55871.phpt +++ b/ext/standard/tests/strings/bug55871.phpt @@ -41,6 +41,8 @@ array(1) { [0]=> string(0) "" } + +Warning: A non-numeric value encountered in %s on line %d array(1) { [0]=> string(40) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" diff --git a/ext/standard/type.c b/ext/standard/type.c index d6a412f4ec4..529d666d02d 100644 --- a/ext/standard/type.c +++ b/ext/standard/type.c @@ -154,7 +154,7 @@ PHP_FUNCTION(intval) ZEND_PARSE_PARAMETERS_END(); #endif - if (Z_TYPE_P(num) != IS_STRING) { + if (Z_TYPE_P(num) != IS_STRING || base == 10) { RETVAL_LONG(zval_get_long(num)); } else { RETVAL_LONG(ZEND_STRTOL(Z_STRVAL_P(num), NULL, base)); diff --git a/tests/lang/bug28800.phpt b/tests/lang/bug28800.phpt index f81ad7fec98..8bd2c306e1b 100644 --- a/tests/lang/bug28800.phpt +++ b/tests/lang/bug28800.phpt @@ -7,11 +7,23 @@ Bug #28800 (Incorrect string to number conversion for strings starting with 'inf echo ($v+0)."\n"; } ?> ---EXPECT-- -0 -0 -0 -0 -0 +--EXPECTF-- + +Warning: A non-numeric value encountered in %s on line %d +0 + +Warning: A non-numeric value encountered in %s on line %d +0 + +Warning: A non-numeric value encountered in %s on line %d +0 + +Warning: A non-numeric value encountered in %s on line %d +0 + +Warning: A non-numeric value encountered in %s on line %d +0 + +Warning: A non-numeric value encountered in %s on line %d 0 diff --git a/tests/lang/operators/bitwiseShiftLeft_variationStr_64bit.phpt b/tests/lang/operators/bitwiseShiftLeft_variationStr_64bit.phpt index d5888d837f9..69fd90f1c8c 100644 --- a/tests/lang/operators/bitwiseShiftLeft_variationStr_64bit.phpt +++ b/tests/lang/operators/bitwiseShiftLeft_variationStr_64bit.phpt @@ -226,17 +226,17 @@ int(984) --- testing: '123abc' << 'a5.9' --- int(123) --- testing: '123e5' << '0' --- -int(123) +int(12300000) --- testing: '123e5' << '65' --- int(0) --- testing: '123e5' << '-44' --- Exception: Bit shift by negative number --- testing: '123e5' << '1.2' --- -int(246) +int(24600000) --- testing: '123e5' << '-7.7' --- Exception: Bit shift by negative number --- testing: '123e5' << 'abc' --- -int(123) +int(12300000) --- testing: '123e5' << '123abc' --- int(0) --- testing: '123e5' << '123e5' --- @@ -250,21 +250,21 @@ int(0) --- testing: '123e5' << '123abc ' --- int(0) --- testing: '123e5' << '3.4a' --- -int(984) +int(98400000) --- testing: '123e5' << 'a5.9' --- -int(123) +int(12300000) --- testing: '123e5xyz' << '0' --- -int(123) +int(12300000) --- testing: '123e5xyz' << '65' --- int(0) --- testing: '123e5xyz' << '-44' --- Exception: Bit shift by negative number --- testing: '123e5xyz' << '1.2' --- -int(246) +int(24600000) --- testing: '123e5xyz' << '-7.7' --- Exception: Bit shift by negative number --- testing: '123e5xyz' << 'abc' --- -int(123) +int(12300000) --- testing: '123e5xyz' << '123abc' --- int(0) --- testing: '123e5xyz' << '123e5' --- @@ -278,9 +278,9 @@ int(0) --- testing: '123e5xyz' << '123abc ' --- int(0) --- testing: '123e5xyz' << '3.4a' --- -int(984) +int(98400000) --- testing: '123e5xyz' << 'a5.9' --- -int(123) +int(12300000) --- testing: ' 123abc' << '0' --- int(123) --- testing: ' 123abc' << '65' --- diff --git a/tests/lang/operators/bitwiseShiftRight_variationStr.phpt b/tests/lang/operators/bitwiseShiftRight_variationStr.phpt index a86d0cfddb2..a4c425aab3e 100644 --- a/tests/lang/operators/bitwiseShiftRight_variationStr.phpt +++ b/tests/lang/operators/bitwiseShiftRight_variationStr.phpt @@ -222,17 +222,17 @@ int(15) --- testing: '123abc' >> 'a5.9' --- int(123) --- testing: '123e5' >> '0' --- -int(123) +int(12300000) --- testing: '123e5' >> '65' --- int(0) --- testing: '123e5' >> '-44' --- Exception: Bit shift by negative number --- testing: '123e5' >> '1.2' --- -int(61) +int(6150000) --- testing: '123e5' >> '-7.7' --- Exception: Bit shift by negative number --- testing: '123e5' >> 'abc' --- -int(123) +int(12300000) --- testing: '123e5' >> '123abc' --- int(0) --- testing: '123e5' >> '123e5' --- @@ -246,21 +246,21 @@ int(0) --- testing: '123e5' >> '123abc ' --- int(0) --- testing: '123e5' >> '3.4a' --- -int(15) +int(1537500) --- testing: '123e5' >> 'a5.9' --- -int(123) +int(12300000) --- testing: '123e5xyz' >> '0' --- -int(123) +int(12300000) --- testing: '123e5xyz' >> '65' --- int(0) --- testing: '123e5xyz' >> '-44' --- Exception: Bit shift by negative number --- testing: '123e5xyz' >> '1.2' --- -int(61) +int(6150000) --- testing: '123e5xyz' >> '-7.7' --- Exception: Bit shift by negative number --- testing: '123e5xyz' >> 'abc' --- -int(123) +int(12300000) --- testing: '123e5xyz' >> '123abc' --- int(0) --- testing: '123e5xyz' >> '123e5' --- @@ -274,9 +274,9 @@ int(0) --- testing: '123e5xyz' >> '123abc ' --- int(0) --- testing: '123e5xyz' >> '3.4a' --- -int(15) +int(1537500) --- testing: '123e5xyz' >> 'a5.9' --- -int(123) +int(12300000) --- testing: ' 123abc' >> '0' --- int(123) --- testing: ' 123abc' >> '65' --- diff --git a/tests/lang/operators/modulus_variationStr.phpt b/tests/lang/operators/modulus_variationStr.phpt index c647ecd3805..4cfd7768ffe 100644 --- a/tests/lang/operators/modulus_variationStr.phpt +++ b/tests/lang/operators/modulus_variationStr.phpt @@ -208,9 +208,9 @@ Exception: Modulo by zero --- testing: '123abc' % '123abc' --- int(0) --- testing: '123abc' % '123e5' --- -int(0) +int(123) --- testing: '123abc' % '123e5xyz' --- -int(0) +int(123) --- testing: '123abc' % ' 123abc' --- int(0) --- testing: '123abc' % '123 abc' --- @@ -224,13 +224,13 @@ Exception: Modulo by zero --- testing: '123e5' % '0' --- Exception: Modulo by zero --- testing: '123e5' % '65' --- -int(58) +int(50) --- testing: '123e5' % '-44' --- -int(35) +int(20) --- testing: '123e5' % '1.2' --- int(0) --- testing: '123e5' % '-7.7' --- -int(4) +int(6) --- testing: '123e5' % 'abc' --- Exception: Modulo by zero --- testing: '123e5' % '123abc' --- @@ -252,13 +252,13 @@ Exception: Modulo by zero --- testing: '123e5xyz' % '0' --- Exception: Modulo by zero --- testing: '123e5xyz' % '65' --- -int(58) +int(50) --- testing: '123e5xyz' % '-44' --- -int(35) +int(20) --- testing: '123e5xyz' % '1.2' --- int(0) --- testing: '123e5xyz' % '-7.7' --- -int(4) +int(6) --- testing: '123e5xyz' % 'abc' --- Exception: Modulo by zero --- testing: '123e5xyz' % '123abc' --- @@ -292,9 +292,9 @@ Exception: Modulo by zero --- testing: ' 123abc' % '123abc' --- int(0) --- testing: ' 123abc' % '123e5' --- -int(0) +int(123) --- testing: ' 123abc' % '123e5xyz' --- -int(0) +int(123) --- testing: ' 123abc' % ' 123abc' --- int(0) --- testing: ' 123abc' % '123 abc' --- @@ -320,9 +320,9 @@ Exception: Modulo by zero --- testing: '123 abc' % '123abc' --- int(0) --- testing: '123 abc' % '123e5' --- -int(0) +int(123) --- testing: '123 abc' % '123e5xyz' --- -int(0) +int(123) --- testing: '123 abc' % ' 123abc' --- int(0) --- testing: '123 abc' % '123 abc' --- @@ -348,9 +348,9 @@ Exception: Modulo by zero --- testing: '123abc ' % '123abc' --- int(0) --- testing: '123abc ' % '123e5' --- -int(0) +int(123) --- testing: '123abc ' % '123e5xyz' --- -int(0) +int(123) --- testing: '123abc ' % ' 123abc' --- int(0) --- testing: '123abc ' % '123 abc' --- diff --git a/tests/lang/operators/negate_variationStr.phpt b/tests/lang/operators/negate_variationStr.phpt index a25bdda7f59..7405d42882e 100644 --- a/tests/lang/operators/negate_variationStr.phpt +++ b/tests/lang/operators/negate_variationStr.phpt @@ -16,7 +16,7 @@ foreach ($strVals as $strVal) { ?> ===DONE=== ---EXPECT-- +--EXPECTF-- --- testing: '0' --- int(0) --- testing: '65' --- @@ -28,21 +28,37 @@ float(-1.2) --- testing: '-7.7' --- float(7.7) --- testing: 'abc' --- + +Warning: A non-numeric value encountered in %s on line %d int(0) --- testing: '123abc' --- + +Notice: A non well formed numeric value encountered in %s on line %d int(-123) --- testing: '123e5' --- float(-12300000) --- testing: '123e5xyz' --- + +Notice: A non well formed numeric value encountered in %s on line %d float(-12300000) --- testing: ' 123abc' --- + +Notice: A non well formed numeric value encountered in %s on line %d int(-123) --- testing: '123 abc' --- + +Notice: A non well formed numeric value encountered in %s on line %d int(-123) --- testing: '123abc ' --- + +Notice: A non well formed numeric value encountered in %s on line %d int(-123) --- testing: '3.4a' --- + +Notice: A non well formed numeric value encountered in %s on line %d float(-3.4) --- testing: 'a5.9' --- + +Warning: A non-numeric value encountered in %s on line %d int(0) ===DONE=== From 3bfe1c55ae72f6f2c1cccc641e46f26114376ecd Mon Sep 17 00:00:00 2001 From: Matteo Beccati Date: Wed, 30 Mar 2016 10:00:28 +0200 Subject: [PATCH 03/14] Removed shmop test leaking an shm segment --- ext/shmop/shmop.c | 1 + ext/shmop/tests/003.phpt | 33 --------------------------------- 2 files changed, 1 insertion(+), 33 deletions(-) delete mode 100644 ext/shmop/tests/003.phpt diff --git a/ext/shmop/shmop.c b/ext/shmop/shmop.c index 4fe65ae37d0..d647790aa06 100644 --- a/ext/shmop/shmop.c +++ b/ext/shmop/shmop.c @@ -203,6 +203,7 @@ PHP_FUNCTION(shmop_open) } if (shmctl(shmop->shmid, IPC_STAT, &shm)) { + /* please do not add coverage here: the segment would be leaked and impossible to delete via php */ php_error_docref(NULL, E_WARNING, "unable to get shared memory segment information '%s'", strerror(errno)); goto err; } diff --git a/ext/shmop/tests/003.phpt b/ext/shmop/tests/003.phpt deleted file mode 100644 index 1c154f08ca0..00000000000 --- a/ext/shmop/tests/003.phpt +++ /dev/null @@ -1,33 +0,0 @@ ---TEST-- -shmop extension error messages (non-root) ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -## shmop_open function tests ## - -Warning: shmop_open(): unable to get shared memory segment information 'Permission denied' in %s on line %d -bool(false) From 5be140004d8079dca6e91801c1857d1119bf4408 Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Wed, 30 Mar 2016 13:26:27 +0100 Subject: [PATCH 04/14] Expand UPGRADING and NEWS re: numeric strings changes --- NEWS | 6 +++--- UPGRADING | 13 ++++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index af7a2afe12c..dfbc707d7ab 100644 --- a/NEWS +++ b/NEWS @@ -17,9 +17,9 @@ PHP NEWS . Added a form of the list() construct where keys can be specified. (Andrea) . Number operators taking numeric strings now emit E_NOTICEs or E_WARNINGs when given malformed numeric strings. (Andrea) - . (int), intval() where $base is 10 or unspecified, settype(), integer - operators and other conversions now always respect scientific notation in - numeric strings. (Andrea) + . (int), intval() where $base is 10 or unspecified, settype(), decbin(), + decoct(), dechex(), integer operators and other conversions now always + respect scientific notation in numeric strings. (Andrea) - FTP: . Implemented FR #55651 (Option to ignore the returned FTP PASV address). diff --git a/UPGRADING b/UPGRADING index bda00da7db7..ad3b15f0ee3 100644 --- a/UPGRADING +++ b/UPGRADING @@ -21,9 +21,9 @@ PHP 7.1 UPGRADE NOTES - Core: . 'void' can no longer be used as the name of a class, interface, or trait. This applies to declarations, class_alias() and use statements. - . (int), intval() where $base is 10 or unspecified, settype(), integer - operators and other conversions now always respect scientific notation in - numeric strings. + . (int), intval() where $base is 10 or unspecified, settype(), decbin(), + decoct(), dechex(), integer operators and other conversions now always + respect scientific notation in numeric strings. (RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic) - JSON: @@ -44,6 +44,13 @@ PHP 7.1 UPGRADE NOTES . Number operators taking numeric strings now emit "A non well formed numeric string encountered" E_NOTICEs for leading-numeric strings, and "A non-numeric string encountered" E_WARNINGs for non-numeric strings. + This always applies to the +, -, *, /, **, %, << and >> operators, and + their assignment counterparts +=, -=, *=, /=, **=, %=, <<= and >>=. + For the bitwise operators |, & and ^, and their assignment counterparts + |=, &= and ^=, this only applies where only one operand is a string. + Note that this never applies to the bitwise NOT operator, ~, which does not + handle numeric strings, nor to the increment and decrement operators + ++ and --, which have a unique approach to handling numeric strings. (RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic) ======================================== From 6ce873b54648030727d20e8012a3dfac515ef748 Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Wed, 30 Mar 2016 13:48:51 +0100 Subject: [PATCH 05/14] Fix two tests on 32-bit --- Zend/tests/numeric_string_errors.phpt | 2 +- Zend/tests/numeric_string_errors_assign.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Zend/tests/numeric_string_errors.phpt b/Zend/tests/numeric_string_errors.phpt index 26ceea7dee7..e98c58dda72 100644 --- a/Zend/tests/numeric_string_errors.phpt +++ b/Zend/tests/numeric_string_errors.phpt @@ -123,7 +123,7 @@ Warning: A non-numeric value encountered in %s on line %d Notice: A non well formed numeric value encountered in %s on line %d Notice: A non well formed numeric value encountered in %s on line %d -int(360639813910528) +int(%d) Warning: A non-numeric value encountered in %s on line %d diff --git a/Zend/tests/numeric_string_errors_assign.phpt b/Zend/tests/numeric_string_errors_assign.phpt index 7fb8898fc99..8d882aadccd 100644 --- a/Zend/tests/numeric_string_errors_assign.phpt +++ b/Zend/tests/numeric_string_errors_assign.phpt @@ -178,7 +178,7 @@ Warning: A non-numeric value encountered in %s on line %d Notice: A non well formed numeric value encountered in %s on line %d Notice: A non well formed numeric value encountered in %s on line %d -int(360639813910528) +int(%d) Warning: A non-numeric value encountered in %s on line %d From d6fc6d4ae6f9ce0b3e0d1fc6bd6b0e6b385f2127 Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Wed, 30 Mar 2016 14:16:07 +0100 Subject: [PATCH 06/14] Fix memory leak Leak was introduced in c88ffa9a5673cb3141660626ba1921671f0b84d6. --- ext/opcache/Optimizer/zend_call_graph.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ext/opcache/Optimizer/zend_call_graph.c b/ext/opcache/Optimizer/zend_call_graph.c index bbc6fb54f93..ef586e12a73 100644 --- a/ext/opcache/Optimizer/zend_call_graph.c +++ b/ext/opcache/Optimizer/zend_call_graph.c @@ -260,6 +260,8 @@ static void zend_analyze_recursion(zend_call_graph *call_graph) call_info = call_info->next_caller; } } + + free_alloca(visited, use_heap); } static void zend_sort_op_arrays(zend_call_graph *call_graph) From 0105bd20b706c8ab5b0a71f59f11a9dabe735f6b Mon Sep 17 00:00:00 2001 From: Andrea Faulds Date: Wed, 30 Mar 2016 16:45:36 +0100 Subject: [PATCH 07/14] Correct error messages --- UPGRADING | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UPGRADING b/UPGRADING index ad3b15f0ee3..9c94fd09a92 100644 --- a/UPGRADING +++ b/UPGRADING @@ -42,8 +42,8 @@ PHP 7.1 UPGRADE NOTES . Added a form of the list() construct where keys can be specified. (RFC: https://wiki.php.net/rfc/list_keys) . Number operators taking numeric strings now emit "A non well formed numeric - string encountered" E_NOTICEs for leading-numeric strings, and "A - non-numeric string encountered" E_WARNINGs for non-numeric strings. + value encountered" E_NOTICEs for leading-numeric strings, and "A + non-numeric value encountered" E_WARNINGs for non-numeric strings. This always applies to the +, -, *, /, **, %, << and >> operators, and their assignment counterparts +=, -=, *=, /=, **=, %=, <<= and >>=. For the bitwise operators |, & and ^, and their assignment counterparts From f95679885ff9a7258f0a91b9d83d73a7ee7e6f91 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 30 Mar 2016 18:31:10 +0200 Subject: [PATCH 08/14] Fix __invoke comparison in closure_get_method It compared against the wrong variable. Fixed this by getting rid of lc_name entirely and use equals_literal_ci instead. --- Zend/tests/closure_invoke_case_insensitive.phpt | 16 ++++++++++++++++ Zend/zend_closures.c | 8 ++------ 2 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/closure_invoke_case_insensitive.phpt diff --git a/Zend/tests/closure_invoke_case_insensitive.phpt b/Zend/tests/closure_invoke_case_insensitive.phpt new file mode 100644 index 00000000000..d41d58a747c --- /dev/null +++ b/Zend/tests/closure_invoke_case_insensitive.phpt @@ -0,0 +1,16 @@ +--TEST-- +Closure::__invoke() is case insensitive +--FILE-- +__INVOKE($n); +var_dump($n); + +?> +--EXPECT-- +int(2) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 9b4fb1180e8..def114c4ec5 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -297,14 +297,10 @@ ZEND_API zval* zend_get_closure_this_ptr(zval *obj) /* {{{ */ static zend_function *zend_closure_get_method(zend_object **object, zend_string *method, const zval *key) /* {{{ */ { - zend_string *lc_name; - - lc_name = zend_string_tolower(method); - if (zend_string_equals_literal(method, ZEND_INVOKE_FUNC_NAME)) { - zend_string_release(lc_name); + if (zend_string_equals_literal_ci(method, ZEND_INVOKE_FUNC_NAME)) { return zend_get_closure_invoke_method(*object); } - zend_string_release(lc_name); + return std_object_handlers.get_method(object, method, key); } /* }}} */ From abd59c0e400173d36abe49930bd56b8d37b0dfc1 Mon Sep 17 00:00:00 2001 From: Ferenc Kovacs Date: Wed, 30 Mar 2016 22:28:28 +0200 Subject: [PATCH 09/14] update NEWS --- NEWS | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/NEWS b/NEWS index 1f2a906f81c..20cb8767623 100644 --- a/NEWS +++ b/NEWS @@ -48,9 +48,19 @@ PHP NEWS - Date: . Fixed bug #71635 (DatePeriod::getEndDate segfault). (Thomas Punt) +- Fileinfo: + . Fixed bug #71527 (Buffer over-write in finfo_open with malformed magic + file). (Anatol) + +- Mbstring: + . Fixed bug #71906 (AddressSanitizer: negative-size-param (-1) in + mbfl_strcut). (Stas) + - ODBC: . Fixed bug #47803, #69526 (Executing prepared statements is succesfull only for the first two statements). (einavitamar at gmail dot com, Anatol) + . Fixed bug #71860 (Invalid memory write in phar on filename with \0 in + name). (Stas) - PDO_DBlib: . Bug #54648 (PDO::MSSQL forces format of datetime fields). @@ -62,6 +72,14 @@ PHP NEWS . Fixed bug #71504 (Parsing of tar file with duplicate filenames causes memory leak). (Jos Elstgeest) +- SNMP: + . Fixed bug #71704 (php_snmp_error() Format String Vulnerability). + (andrew at jmpesp dot org) + +- Standard + . Fixed bug #71798 (Integer Overflow in php_raw_url_encode). + (taoguangchen at icloud dot com, Stas) + 03 Mar 2016, PHP 5.6.19 - CLI server: From b1e854f7762b2e0648ddc240835cb446ee4d20a7 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 12 Jan 2016 16:31:58 +0100 Subject: [PATCH 10/14] Fix bug #71334 Always duplicate the array before doing a sort with user-defined comparison function, to avoid access to the intermediate inconsistent state. I've also dropped the "array modification" warning, as protection against modifications is no longer relevant if we're always working on a copy anyway. This also required some changes to how SplArray forwards calls to sorting functions. --- NEWS | 1 + ext/spl/spl_array.c | 45 ++++++++++++------- ext/standard/array.c | 35 ++++++--------- ext/standard/tests/array/bug71334.phpt | 38 ++++++++++++++++ .../tests/array/unexpected_array_mod_bug.phpt | 21 ++++++--- .../unexpected_array_mod_bug_variation1.phpt | 33 ++++++++++++++ 6 files changed, 131 insertions(+), 42 deletions(-) create mode 100644 ext/standard/tests/array/bug71334.phpt create mode 100644 ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt diff --git a/NEWS b/NEWS index abf70d04c1f..b8e4eefe090 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ PHP NEWS . Fixed bug #62059 (ArrayObject and isset are not friends). (Nikita) . Fixed bug #71871 (Interfaces allow final and abstract functions). (Nikita) . Fixed bug #71922 (Crash on assert(new class{})). (Nikita) + . Fixed bug #71334 (Cannot access array keys while uksort()). (Nikita) - Curl: . Fixed bug #71831 (CURLOPT_NOPROXY applied as long instead of string). diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index d5cb32606ea..60cbac57269 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -82,18 +82,18 @@ static inline spl_array_object *spl_array_from_obj(zend_object *obj) /* {{{ */ { #define Z_SPLARRAY_P(zv) spl_array_from_obj(Z_OBJ_P((zv))) -static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* {{{ */ +static inline HashTable **spl_array_get_hash_table_ptr(spl_array_object* intern) { /* {{{ */ //??? TODO: Delay duplication for arrays; only duplicate for write operations if (intern->ar_flags & SPL_ARRAY_IS_SELF) { if (!intern->std.properties) { rebuild_object_properties(&intern->std); } - return intern->std.properties; + return &intern->std.properties; } else if (intern->ar_flags & SPL_ARRAY_USE_OTHER) { spl_array_object *other = Z_SPLARRAY_P(&intern->array); - return spl_array_get_hash_table(other); + return spl_array_get_hash_table_ptr(other); } else if (Z_TYPE(intern->array) == IS_ARRAY) { - return Z_ARRVAL(intern->array); + return &Z_ARRVAL(intern->array); } else { zend_object *obj = Z_OBJ(intern->array); if (!obj->properties) { @@ -104,9 +104,22 @@ static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* } obj->properties = zend_array_dup(obj->properties); } - return obj->properties; + return &obj->properties; } -} /* }}} */ +} +/* }}} */ + +static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* {{{ */ + return *spl_array_get_hash_table_ptr(intern); +} +/* }}} */ + +static inline void spl_array_replace_hash_table(spl_array_object* intern, HashTable *ht) { /* {{{ */ + HashTable **ht_ptr = spl_array_get_hash_table_ptr(intern); + zend_array_destroy(*ht_ptr); + *ht_ptr = ht; +} +/* }}} */ static inline zend_bool spl_array_is_object(spl_array_object *intern) /* {{{ */ { @@ -1432,16 +1445,12 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam spl_array_object *intern = Z_SPLARRAY_P(getThis()); HashTable *aht = spl_array_get_hash_table(intern); zval function_name, params[2], *arg = NULL; - uint32_t old_refcount; ZVAL_STRINGL(&function_name, fname, fname_len); - /* A tricky way to pass "aht" by reference, reset refcount */ - //??? It may be not safe, if user comparison handler accesses "aht" - old_refcount = GC_REFCOUNT(aht); - GC_REFCOUNT(aht) = 1; ZVAL_NEW_EMPTY_REF(¶ms[0]); ZVAL_ARR(Z_REFVAL(params[0]), aht); + GC_REFCOUNT(aht)++; if (!use_arg) { intern->nApplyCount++; @@ -1470,10 +1479,16 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam } exit: - /* A tricky way to pass "aht" by reference, copy back and cleanup */ - GC_REFCOUNT(aht) = old_refcount; - efree(Z_REF(params[0])); - zend_string_free(Z_STR(function_name)); + { + HashTable *new_ht = Z_ARRVAL_P(Z_REFVAL(params[0])); + if (aht != new_ht) { + spl_array_replace_hash_table(intern, new_ht); + } else { + GC_REFCOUNT(aht)--; + } + efree(Z_REF(params[0])); + zend_string_free(Z_STR(function_name)); + } } /* }}} */ #define SPL_ARRAY_METHOD(cname, fname, use_arg) \ diff --git a/ext/standard/array.c b/ext/standard/array.c index 4ff373a0b02..289870ac1f2 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1035,38 +1035,31 @@ static int php_array_user_compare(const void *a, const void *b) /* {{{ */ static void php_usort(INTERNAL_FUNCTION_PARAMETERS, compare_func_t compare_func, zend_bool renumber) /* {{{ */ { zval *array; - zend_refcounted *arr; + zend_array *arr; zend_bool retval; PHP_ARRAY_CMP_FUNC_VARS; PHP_ARRAY_CMP_FUNC_BACKUP(); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/f", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "af", &array, &BG(user_compare_fci), &BG(user_compare_fci_cache)) == FAILURE) { PHP_ARRAY_CMP_FUNC_RESTORE(); return; } - /* Increase reference counter, so the attempts to modify the array in user - * comparison function will create a copy of array and won't affect the - * original array. The fact of modification is detected by comparing the - * zend_array pointer. The result of sorting in such case is undefined and - * the function returns FALSE. - */ - Z_ADDREF_P(array); - arr = Z_COUNTED_P(array); - - retval = zend_hash_sort(Z_ARRVAL_P(array), compare_func, renumber) != FAILURE; - - if (arr != Z_COUNTED_P(array)) { - php_error_docref(NULL, E_WARNING, "Array was modified by the user comparison function"); - if (--GC_REFCOUNT(arr) <= 0) { - _zval_dtor_func(arr ZEND_FILE_LINE_CC); - } - retval = 0; - } else { - Z_DELREF_P(array); + arr = Z_ARR_P(array); + if (zend_hash_num_elements(arr) == 0) { + PHP_ARRAY_CMP_FUNC_RESTORE(); + RETURN_TRUE; } + /* Copy array, so the in-place modifications will not be visible to the callback function */ + arr = zend_array_dup(arr); + + retval = zend_hash_sort(arr, compare_func, renumber) != FAILURE; + + zval_ptr_dtor(array); + ZVAL_ARR(array, arr); + PHP_ARRAY_CMP_FUNC_RESTORE(); RETURN_BOOL(retval); } diff --git a/ext/standard/tests/array/bug71334.phpt b/ext/standard/tests/array/bug71334.phpt new file mode 100644 index 00000000000..7a37d0953a4 --- /dev/null +++ b/ext/standard/tests/array/bug71334.phpt @@ -0,0 +1,38 @@ +--TEST-- +Bug #71334: Cannot access array keys while uksort() +--FILE-- + [1], + '-' => [2], + 'bar-test' => [3] + ]; + + private function _mySort($x, $y) + { + if (!isset($this->a[$x])) { + throw new Exception('Missing X: "' . $x . '"'); + } + + if (!isset($this->a[$y])) { + throw new Exception('Missing Y: "' . $y . '"'); + } + + return $x < $y; + } + + public function __construct() + { + uksort($this->a, [$this, '_mySort']); + } +} + +new myClass(); +echo "Done"; + +?> +--EXPECT-- +Done diff --git a/ext/standard/tests/array/unexpected_array_mod_bug.phpt b/ext/standard/tests/array/unexpected_array_mod_bug.phpt index 58f22492054..2762ebd8309 100644 --- a/ext/standard/tests/array/unexpected_array_mod_bug.phpt +++ b/ext/standard/tests/array/unexpected_array_mod_bug.phpt @@ -4,7 +4,7 @@ Crash when function parameter modified via reference $b; } $my_var = array(1 => "entry_1", 2 => "entry_2", @@ -12,10 +12,19 @@ $my_var = array(1 => "entry_1", 4 => "entry_4", 5 => "entry_5"); usort($my_var, "usercompare"); +var_dump($my_var); -echo "Done.\n"; ?> ---EXPECTF-- - -Warning: usort(): Array was modified by the user comparison function in %s on line %d -Done. +--EXPECT-- +array(5) { + [0]=> + string(7) "entry_1" + [1]=> + string(7) "entry_2" + [2]=> + string(7) "entry_3" + [3]=> + string(7) "entry_4" + [4]=> + string(7) "entry_5" +} diff --git a/ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt b/ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt new file mode 100644 index 00000000000..b5a1ee24d59 --- /dev/null +++ b/ext/standard/tests/array/unexpected_array_mod_bug_variation1.phpt @@ -0,0 +1,33 @@ +--TEST-- +Crash when function parameter modified via reference while keeping orig refcount +--FILE-- + "entry_1", + 2 => "entry_2", + 3 => "entry_3", + 4 => "entry_4", + 5 => "entry_5" +); +usort($array, function($a, $b) use (&$array, &$ref) { + unset($array[2]); + $ref = $array; + return $a <=> $b; +}); +var_dump($array); + +?> +--EXPECT-- +array(5) { + [0]=> + string(7) "entry_1" + [1]=> + string(7) "entry_2" + [2]=> + string(7) "entry_3" + [3]=> + string(7) "entry_4" + [4]=> + string(7) "entry_5" +} From cef40c0c3fe05beb58ed8d4bc8bbf9658ab64a71 Mon Sep 17 00:00:00 2001 From: Lior Kaplan Date: Thu, 31 Mar 2016 00:52:53 +0300 Subject: [PATCH 11/14] Align NEWS entry format --- NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 20cb8767623..e72c7ca911d 100644 --- a/NEWS +++ b/NEWS @@ -21,8 +21,8 @@ PHP NEWS (Daniel kalaspuffar, Julien) - Postgres: - . Fixed bug #71820 (pg_fetch_object binds parameters before - call constructor). (Anatol) + . Fixed bug #71820 (pg_fetch_object binds parameters before call + constructor). (Anatol) - SPL: . Fixed bug #67582 (Cloned SplObjectStorage with overwritten getHash fails @@ -63,7 +63,7 @@ PHP NEWS name). (Stas) - PDO_DBlib: - . Bug #54648 (PDO::MSSQL forces format of datetime fields). + . Fixed bug #54648 (PDO::MSSQL forces format of datetime fields). (steven dot lambeth at gmx dot de, Anatol) - Phar: From 3b26af59d413ce599a5f0361aa3d132d5652cb3a Mon Sep 17 00:00:00 2001 From: Lior Kaplan Date: Thu, 31 Mar 2016 01:01:11 +0300 Subject: [PATCH 12/14] Align NEWS entry format --- NEWS | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index b8e4eefe090..b81998b5d26 100644 --- a/NEWS +++ b/NEWS @@ -33,8 +33,8 @@ PHP NEWS (Daniel kalaspuffar, Julien) - Postgres: - . Fixed bug #71820 (pg_fetch_object binds parameters before - call constructor). (Anatol) + . Fixed bug #71820 (pg_fetch_object binds parameters before call + constructor). (Anatol) - SPL: . Fixed bug #71838 (Deserializing serialized SPLObjectStorage-Object can't @@ -117,8 +117,7 @@ PHP NEWS (steven dot lambeth at gmx dot de, Anatol) - Phar: - . Fixed bug #71625 (Crash in php7.dll with bad phar filename). - (Anatol) + . Fixed bug #71625 (Crash in php7.dll with bad phar filename). (Anatol) . Fixed bug #71317 (PharData fails to open specific file). (Jos Elstgeest) . Fixed bug #71860 (Invalid memory write in phar on filename with \0 in name). (Stas) @@ -127,7 +126,7 @@ PHP NEWS . Fixed crash when advancing (except step) inside an internal function. (Bob) - Session: - . Fixed Bug #71683 (Null pointer dereference in zend_hash_str_find_bucket). + . Fixed bug #71683 (Null pointer dereference in zend_hash_str_find_bucket). (Yasuo) - SNMP: From ed707a521738fa7269b1992a6738bfef44662f46 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Thu, 31 Mar 2016 01:29:05 +0200 Subject: [PATCH 13/14] fix test to not to cause false positives --- ext/fileinfo/tests/bug68996.phpt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ext/fileinfo/tests/bug68996.phpt b/ext/fileinfo/tests/bug68996.phpt index da208d35bcc..214e52fa6f7 100644 --- a/ext/fileinfo/tests/bug68996.phpt +++ b/ext/fileinfo/tests/bug68996.phpt @@ -1,11 +1,14 @@ --TEST-- Bug #68996 (Invalid free of CG(interned_empty_string)) --SKIPIF-- + --INI-- html_errors=1 ---ENV-- -USE_ZEND_ALLOC=0 --FILE-- Date: Thu, 31 Mar 2016 01:33:38 +0200 Subject: [PATCH 14/14] fix borked mainstream patch --- ext/fileinfo/libmagic/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c index def2f7b31bc..b976ac9a49b 100644 --- a/ext/fileinfo/libmagic/funcs.c +++ b/ext/fileinfo/libmagic/funcs.c @@ -414,7 +414,7 @@ file_check_mem(struct magic_set *ms, unsigned int level) size_t len; if (level >= ms->c.len) { - len = (ms->c.len += 20 + level) * sizeof(*ms->c.li); + len = (ms->c.len = 20 + level) * sizeof(*ms->c.li); ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ? emalloc(len) : erealloc(ms->c.li, len));