From 48a076403fd30ed246853e25b6b049a883a75be5 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 21 Nov 2022 12:48:52 +0000 Subject: [PATCH 01/23] Add more behavioural tests for incdec operators --- Zend/tests/decrement_001.phpt | 67 ------------ Zend/tests/decrement_001_64bit.phpt | 67 ------------ Zend/tests/in-de-crement/decrement_001.phpt | 25 +++++ .../in-de-crement/decrement_001_64bit.phpt | 25 +++++ .../incdec_ref_property.phpt | 0 Zend/tests/in-de-crement/incdec_strings.phpt | 102 ++++++++++++++++++ Zend/tests/in-de-crement/incdec_types.phpt | 82 ++++++++++++++ .../{ => in-de-crement}/incdec_undef.phpt | 0 Zend/tests/in-de-crement/increment_001.phpt | 24 +++++ .../in-de-crement/increment_001_64bit.phpt | 24 +++++ .../increment_function_return_error.phpt | 0 Zend/tests/increment_001.phpt | 67 ------------ 12 files changed, 282 insertions(+), 201 deletions(-) delete mode 100644 Zend/tests/decrement_001.phpt delete mode 100644 Zend/tests/decrement_001_64bit.phpt create mode 100644 Zend/tests/in-de-crement/decrement_001.phpt create mode 100644 Zend/tests/in-de-crement/decrement_001_64bit.phpt rename Zend/tests/{ => in-de-crement}/incdec_ref_property.phpt (100%) create mode 100644 Zend/tests/in-de-crement/incdec_strings.phpt create mode 100644 Zend/tests/in-de-crement/incdec_types.phpt rename Zend/tests/{ => in-de-crement}/incdec_undef.phpt (100%) create mode 100644 Zend/tests/in-de-crement/increment_001.phpt create mode 100644 Zend/tests/in-de-crement/increment_001_64bit.phpt rename Zend/tests/{ => in-de-crement}/increment_function_return_error.phpt (100%) delete mode 100644 Zend/tests/increment_001.phpt diff --git a/Zend/tests/decrement_001.phpt b/Zend/tests/decrement_001.phpt deleted file mode 100644 index 6382491799563..0000000000000 --- a/Zend/tests/decrement_001.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -decrementing different variables ---SKIPIF-- - ---INI-- -precision=14 ---FILE-- -getMessage(), "\n"; - } - var_dump($var); -} - -echo "Done\n"; -?> ---EXPECTF-- -Cannot decrement array -array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) -} -int(-1) -int(0) -float(1.5) -int(-1) -string(6) "string" -int(122) -float(1.5) -NULL -bool(true) -bool(false) -Cannot decrement stdClass -object(stdClass)#%d (0) { -} -Cannot decrement array -array(0) { -} -float(-2147483649) -float(-2147483649) -Done diff --git a/Zend/tests/decrement_001_64bit.phpt b/Zend/tests/decrement_001_64bit.phpt deleted file mode 100644 index b776bc5dd3896..0000000000000 --- a/Zend/tests/decrement_001_64bit.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -decrementing different variables ---SKIPIF-- - ---INI-- -precision=14 ---FILE-- -getMessage(), "\n"; - } - var_dump($var); -} - -echo "Done\n"; -?> ---EXPECT-- -Cannot decrement array -array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) -} -int(-1) -int(0) -float(1.5) -int(-1) -string(6) "string" -int(122) -float(1.5) -NULL -bool(true) -bool(false) -Cannot decrement stdClass -object(stdClass)#1 (0) { -} -Cannot decrement array -array(0) { -} -float(-9.223372036854776E+18) -float(-9.223372036854776E+18) -Done diff --git a/Zend/tests/in-de-crement/decrement_001.phpt b/Zend/tests/in-de-crement/decrement_001.phpt new file mode 100644 index 0000000000000..63d5ae9975c0b --- /dev/null +++ b/Zend/tests/in-de-crement/decrement_001.phpt @@ -0,0 +1,25 @@ +--TEST-- +Decrementing min int values 32bit +--SKIPIF-- + +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +float(-2147483649) +float(-2147483649) +Done diff --git a/Zend/tests/in-de-crement/decrement_001_64bit.phpt b/Zend/tests/in-de-crement/decrement_001_64bit.phpt new file mode 100644 index 0000000000000..7bc7e8c07fa1a --- /dev/null +++ b/Zend/tests/in-de-crement/decrement_001_64bit.phpt @@ -0,0 +1,25 @@ +--TEST-- +Decrementing min int values 64bit +--SKIPIF-- + +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +float(-9.223372036854776E+18) +float(-9.223372036854776E+18) +Done diff --git a/Zend/tests/incdec_ref_property.phpt b/Zend/tests/in-de-crement/incdec_ref_property.phpt similarity index 100% rename from Zend/tests/incdec_ref_property.phpt rename to Zend/tests/in-de-crement/incdec_ref_property.phpt diff --git a/Zend/tests/in-de-crement/incdec_strings.phpt b/Zend/tests/in-de-crement/incdec_strings.phpt new file mode 100644 index 0000000000000..b5d63978fccad --- /dev/null +++ b/Zend/tests/in-de-crement/incdec_strings.phpt @@ -0,0 +1,102 @@ +--TEST-- +Inc/dec various strings +--FILE-- + +--EXPECT-- +Using increment: +Initial value:string(0) "" +Result value:string(1) "1" +Initial value:string(1) " " +Result value:string(1) " " +Initial value:string(1) "0" +Result value:int(1) +Initial value:string(4) "15.5" +Result value:float(16.5) +Initial value:string(4) "1e10" +Result value:float(10000000001) +Initial value:string(4) "199A" +Result value:string(4) "199B" +Initial value:string(4) "A199" +Result value:string(4) "A200" +Initial value:string(4) "199Z" +Result value:string(4) "200A" +Initial value:string(4) "Z199" +Result value:string(4) "Z200" +Initial value:string(11) "Hello world" +Result value:string(11) "Hello worle" +Initial value:string(4) "🐘" +Result value:string(4) "🐘" +Using decrement: +Initial value:string(0) "" +Result value:int(-1) +Initial value:string(1) " " +Result value:string(1) " " +Initial value:string(1) "0" +Result value:int(-1) +Initial value:string(4) "15.5" +Result value:float(14.5) +Initial value:string(4) "1e10" +Result value:float(9999999999) +Initial value:string(4) "199A" +Result value:string(4) "199A" +Initial value:string(4) "A199" +Result value:string(4) "A199" +Initial value:string(4) "199Z" +Result value:string(4) "199Z" +Initial value:string(4) "Z199" +Result value:string(4) "Z199" +Initial value:string(11) "Hello world" +Result value:string(11) "Hello world" +Initial value:string(4) "🐘" +Result value:string(4) "🐘" diff --git a/Zend/tests/in-de-crement/incdec_types.phpt b/Zend/tests/in-de-crement/incdec_types.phpt new file mode 100644 index 0000000000000..d39845f6cca5c --- /dev/null +++ b/Zend/tests/in-de-crement/incdec_types.phpt @@ -0,0 +1,82 @@ +--TEST-- +Inc/dec various types +--FILE-- +getMessage(), PHP_EOL; + } + try { + $type--; + } catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; + } +} + +echo "Using increment:\n"; +$values = [null, false, true, 0, 0.0, '', ' ', '0']; +foreach ($values as $value) { + echo "Initial value:"; + var_dump($value); + $value++; + echo "Result value:"; + var_dump($value); +} + +echo "Using decrement:\n"; +$values = [null, false, true, 0, 0.0, '', ' ', '0']; +foreach ($values as $value) { + echo "Initial value:"; + var_dump($value); + $value--; + echo "Result value:"; + var_dump($value); +} +?> +--EXPECT-- +Cannot increment array +Cannot decrement array +Cannot increment stdClass +Cannot decrement stdClass +Cannot increment resource +Cannot decrement resource +Using increment: +Initial value:NULL +Result value:int(1) +Initial value:bool(false) +Result value:bool(false) +Initial value:bool(true) +Result value:bool(true) +Initial value:int(0) +Result value:int(1) +Initial value:float(0) +Result value:float(1) +Initial value:string(0) "" +Result value:string(1) "1" +Initial value:string(1) " " +Result value:string(1) " " +Initial value:string(1) "0" +Result value:int(1) +Using decrement: +Initial value:NULL +Result value:NULL +Initial value:bool(false) +Result value:bool(false) +Initial value:bool(true) +Result value:bool(true) +Initial value:int(0) +Result value:int(-1) +Initial value:float(0) +Result value:float(-1) +Initial value:string(0) "" +Result value:int(-1) +Initial value:string(1) " " +Result value:string(1) " " +Initial value:string(1) "0" +Result value:int(-1) diff --git a/Zend/tests/incdec_undef.phpt b/Zend/tests/in-de-crement/incdec_undef.phpt similarity index 100% rename from Zend/tests/incdec_undef.phpt rename to Zend/tests/in-de-crement/incdec_undef.phpt diff --git a/Zend/tests/in-de-crement/increment_001.phpt b/Zend/tests/in-de-crement/increment_001.phpt new file mode 100644 index 0000000000000..a6f3484dff1c2 --- /dev/null +++ b/Zend/tests/in-de-crement/increment_001.phpt @@ -0,0 +1,24 @@ +--TEST-- +Incrementing max int values 32bit +--SKIPIF-- + +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +float(2147483648) +float(2147483648) +Done diff --git a/Zend/tests/in-de-crement/increment_001_64bit.phpt b/Zend/tests/in-de-crement/increment_001_64bit.phpt new file mode 100644 index 0000000000000..333bbcd460d6f --- /dev/null +++ b/Zend/tests/in-de-crement/increment_001_64bit.phpt @@ -0,0 +1,24 @@ +--TEST-- +Incrementing max int values 64bit +--SKIPIF-- + +--INI-- +precision=14 +--FILE-- + +--EXPECT-- +float(9.223372036854776E+18) +float(9.223372036854776E+18) +Done diff --git a/Zend/tests/increment_function_return_error.phpt b/Zend/tests/in-de-crement/increment_function_return_error.phpt similarity index 100% rename from Zend/tests/increment_function_return_error.phpt rename to Zend/tests/in-de-crement/increment_function_return_error.phpt diff --git a/Zend/tests/increment_001.phpt b/Zend/tests/increment_001.phpt deleted file mode 100644 index f34377192677c..0000000000000 --- a/Zend/tests/increment_001.phpt +++ /dev/null @@ -1,67 +0,0 @@ ---TEST-- -incrementing different variables ---SKIPIF-- - ---INI-- -precision=14 ---FILE-- -getMessage(), "\n"; - } - var_dump($var); -} - -echo "Done\n"; -?> ---EXPECTF-- -Cannot increment array -array(3) { - [0]=> - int(1) - [1]=> - int(2) - [2]=> - int(3) -} -string(1) "1" -int(2) -float(3.5) -int(1) -string(6) "strinh" -int(124) -float(3.5) -int(1) -bool(true) -bool(false) -Cannot increment stdClass -object(stdClass)#%d (0) { -} -Cannot increment array -array(0) { -} -float(2147483648) -float(2147483648) -Done From c19280883537e482b1a6dbe4b37bf18ec3dbc0a0 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 21 Nov 2022 13:08:18 +0000 Subject: [PATCH 02/23] Raise no effect warning if inc/dec operator is used on bool --- Zend/Optimizer/zend_inference.c | 2 +- .../in-de-crement/incdec_bool_exception.phpt | 28 +++++++++++++++++++ Zend/tests/in-de-crement/incdec_types.phpt | 10 ++++++- Zend/zend_operators.c | 6 ++-- 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/in-de-crement/incdec_bool_exception.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 238098af1c5fb..f15b29225a9a1 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -4683,7 +4683,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op case ZEND_POST_INC: case ZEND_PRE_DEC: case ZEND_POST_DEC: - return (t1 & (MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); + return (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); case ZEND_BOOL_NOT: case ZEND_JMPZ: case ZEND_JMPNZ: diff --git a/Zend/tests/in-de-crement/incdec_bool_exception.phpt b/Zend/tests/in-de-crement/incdec_bool_exception.phpt new file mode 100644 index 0000000000000..5071939ea62ab --- /dev/null +++ b/Zend/tests/in-de-crement/incdec_bool_exception.phpt @@ -0,0 +1,28 @@ +--TEST-- +Inc/dec on bool: warning converted to exception +--FILE-- +getMessage(), PHP_EOL; + } + try { + $value--; + } catch (\Exception $e) { + echo $e->getMessage(), PHP_EOL; + } +} +?> +--EXPECT-- +Increment on type bool has no effect +Decrement on type bool has no effect +Increment on type bool has no effect +Decrement on type bool has no effect diff --git a/Zend/tests/in-de-crement/incdec_types.phpt b/Zend/tests/in-de-crement/incdec_types.phpt index d39845f6cca5c..ecc80f8d03130 100644 --- a/Zend/tests/in-de-crement/incdec_types.phpt +++ b/Zend/tests/in-de-crement/incdec_types.phpt @@ -39,7 +39,7 @@ foreach ($values as $value) { var_dump($value); } ?> ---EXPECT-- +--EXPECTF-- Cannot increment array Cannot decrement array Cannot increment stdClass @@ -50,8 +50,12 @@ Using increment: Initial value:NULL Result value:int(1) Initial value:bool(false) + +Warning: Increment on type bool has no effect in %s on line %d Result value:bool(false) Initial value:bool(true) + +Warning: Increment on type bool has no effect in %s on line %d Result value:bool(true) Initial value:int(0) Result value:int(1) @@ -67,8 +71,12 @@ Using decrement: Initial value:NULL Result value:NULL Initial value:bool(false) + +Warning: Decrement on type bool has no effect in %s on line %d Result value:bool(false) Initial value:bool(true) + +Warning: Decrement on type bool has no effect in %s on line %d Result value:bool(true) Initial value:int(0) Result value:int(-1) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 1afce6a1f890a..ae7e7e30bd967 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2621,7 +2621,7 @@ ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1) /* {{{ */ break; case IS_FALSE: case IS_TRUE: - /* Do nothing. */ + zend_error(E_WARNING, "Increment on type bool has no effect"); break; case IS_REFERENCE: op1 = Z_REFVAL_P(op1); @@ -2681,9 +2681,11 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ } break; case IS_NULL: + /* Do nothing. */ + break; case IS_FALSE: case IS_TRUE: - /* Do nothing. */ + zend_error(E_WARNING, "Decrement on type bool has no effect"); break; case IS_REFERENCE: op1 = Z_REFVAL_P(op1); From ac1c208c637e584fd0fa47a2e724c24fd6aa2d55 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 21 Nov 2022 14:05:02 +0000 Subject: [PATCH 03/23] Emit warnings and deprecations for inc/dec with strings --- Zend/Optimizer/zend_inference.c | 2 +- Zend/tests/in-de-crement/incdec_strings.phpt | 34 ++++++++- .../incdec_strings_exception.phpt | 75 +++++++++++++++++++ Zend/tests/in-de-crement/incdec_types.phpt | 8 ++ Zend/zend_operators.c | 17 +++++ ext/opcache/tests/jit/inc_017.phpt | 1 + ext/opcache/tests/jit/inc_018.phpt | 1 + ext/opcache/tests/jit/inc_022.phpt | 3 +- ext/opcache/tests/jit/inc_023.phpt | 9 ++- ext/opcache/tests/jit/inc_024.phpt | 49 +++++++++++- ext/opcache/tests/opt/sccp_035.phpt | 1 + ext/opcache/tests/opt/sccp_038.phpt | 1 + .../lang/operators/postdec_variationStr.phpt | 18 ++++- .../lang/operators/postinc_variationStr.phpt | 18 ++++- tests/lang/operators/predec_variationStr.phpt | 18 ++++- tests/lang/operators/preinc_variationStr.phpt | 36 ++++++++- 16 files changed, 282 insertions(+), 9 deletions(-) create mode 100644 Zend/tests/in-de-crement/incdec_strings_exception.phpt diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index f15b29225a9a1..7a322ea9e7c88 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -4683,7 +4683,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op case ZEND_POST_INC: case ZEND_PRE_DEC: case ZEND_POST_DEC: - return (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); + return (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); case ZEND_BOOL_NOT: case ZEND_JMPZ: case ZEND_JMPNZ: diff --git a/Zend/tests/in-de-crement/incdec_strings.phpt b/Zend/tests/in-de-crement/incdec_strings.phpt index b5d63978fccad..75a43d2d8fdfe 100644 --- a/Zend/tests/in-de-crement/incdec_strings.phpt +++ b/Zend/tests/in-de-crement/incdec_strings.phpt @@ -53,11 +53,15 @@ foreach ($values as $value) { var_dump($value); } ?> ---EXPECT-- +--EXPECTF-- Using increment: Initial value:string(0) "" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(1) "1" Initial value:string(1) " " + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(1) @@ -66,21 +70,37 @@ Result value:float(16.5) Initial value:string(4) "1e10" Result value:float(10000000001) Initial value:string(4) "199A" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "199B" Initial value:string(4) "A199" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "A200" Initial value:string(4) "199Z" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "200A" Initial value:string(4) "Z199" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "Z200" Initial value:string(11) "Hello world" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(11) "Hello worle" Initial value:string(4) "🐘" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "🐘" Using decrement: Initial value:string(0) "" + +Deprecated: Decrement on empty string is deprecated as non-numeric in %s on line %d Result value:int(-1) Initial value:string(1) " " + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(-1) @@ -89,14 +109,26 @@ Result value:float(14.5) Initial value:string(4) "1e10" Result value:float(9999999999) Initial value:string(4) "199A" + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(4) "199A" Initial value:string(4) "A199" + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(4) "A199" Initial value:string(4) "199Z" + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(4) "199Z" Initial value:string(4) "Z199" + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(4) "Z199" Initial value:string(11) "Hello world" + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(11) "Hello world" Initial value:string(4) "🐘" + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(4) "🐘" diff --git a/Zend/tests/in-de-crement/incdec_strings_exception.phpt b/Zend/tests/in-de-crement/incdec_strings_exception.phpt new file mode 100644 index 0000000000000..b8b5d865bba2d --- /dev/null +++ b/Zend/tests/in-de-crement/incdec_strings_exception.phpt @@ -0,0 +1,75 @@ +--TEST-- +Inc/dec on string: warning/deprecations converted to exception +--FILE-- +getMessage(), PHP_EOL; + } + var_dump($value); + try { + $value--; + } catch (\Exception $e) { + echo $e->getMessage(), PHP_EOL; + } + var_dump($value); +} +?> +--EXPECT-- +Deprecated: Increment on non-numeric string is deprecated +string(0) "" +Deprecated: Decrement on empty string is deprecated as non-numeric +string(0) "" +Deprecated: Increment on non-numeric string is deprecated +string(1) " " +Warning: Decrement on non-numeric string has no effect +string(1) " " +Deprecated: Increment on non-numeric string is deprecated +string(4) "199A" +Warning: Decrement on non-numeric string has no effect +string(4) "199A" +Deprecated: Increment on non-numeric string is deprecated +string(4) "A199" +Warning: Decrement on non-numeric string has no effect +string(4) "A199" +Deprecated: Increment on non-numeric string is deprecated +string(4) "199Z" +Warning: Decrement on non-numeric string has no effect +string(4) "199Z" +Deprecated: Increment on non-numeric string is deprecated +string(4) "Z199" +Warning: Decrement on non-numeric string has no effect +string(4) "Z199" +Deprecated: Increment on non-numeric string is deprecated +string(11) "Hello world" +Warning: Decrement on non-numeric string has no effect +string(11) "Hello world" +Deprecated: Increment on non-numeric string is deprecated +string(4) "🐘" +Warning: Decrement on non-numeric string has no effect +string(4) "🐘" diff --git a/Zend/tests/in-de-crement/incdec_types.phpt b/Zend/tests/in-de-crement/incdec_types.phpt index ecc80f8d03130..a61335a4ae175 100644 --- a/Zend/tests/in-de-crement/incdec_types.phpt +++ b/Zend/tests/in-de-crement/incdec_types.phpt @@ -62,8 +62,12 @@ Result value:int(1) Initial value:float(0) Result value:float(1) Initial value:string(0) "" + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(1) "1" Initial value:string(1) " " + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(1) @@ -83,8 +87,12 @@ Result value:int(-1) Initial value:float(0) Result value:float(-1) Initial value:string(0) "" + +Deprecated: Decrement on empty string is deprecated as non-numeric in %s on line %d Result value:int(-1) Initial value:string(1) " " + +Warning: Decrement on non-numeric string has no effect in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(-1) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index ae7e7e30bd967..42806c393d9bb 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2502,6 +2502,11 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ int last=0; /* Shut up the compiler warning */ int ch; + zend_error(E_DEPRECATED, "Increment on non-numeric string is deprecated"); + if (EG(exception)) { + return; + } + if (Z_STRLEN_P(str) == 0) { zval_ptr_dtor_str(str); ZVAL_CHAR(str, '1'); @@ -2615,6 +2620,9 @@ ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1) /* {{{ */ default: /* Perl style string increment */ increment_string(op1); + if (EG(exception)) { + return FAILURE; + } break; } } @@ -2660,6 +2668,10 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ break; case IS_STRING: /* Like perl we only support string increment */ if (Z_STRLEN_P(op1) == 0) { /* consider as 0 */ + zend_error(E_DEPRECATED, "Decrement on empty string is deprecated as non-numeric"); + if (EG(exception)) { + return FAILURE; + } zval_ptr_dtor_str(op1); ZVAL_LONG(op1, -1); break; @@ -2678,6 +2690,11 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ zval_ptr_dtor_str(op1); ZVAL_DOUBLE(op1, dval - 1); break; + default: + zend_error(E_WARNING, "Decrement on non-numeric string has no effect"); + if (EG(exception)) { + return FAILURE; + } } break; case IS_NULL: diff --git a/ext/opcache/tests/jit/inc_017.phpt b/ext/opcache/tests/jit/inc_017.phpt index 1d7c0f3d7b9ee..a9cabcd7ad3d3 100644 --- a/ext/opcache/tests/jit/inc_017.phpt +++ b/ext/opcache/tests/jit/inc_017.phpt @@ -18,4 +18,5 @@ function foo() { var_dump(foo()); ?> --EXPECT-- +Warning: Increment on bool has no effect in Unknown on line 0 bool(true) diff --git a/ext/opcache/tests/jit/inc_018.phpt b/ext/opcache/tests/jit/inc_018.phpt index 65c5f0e04ae65..895136e0f2501 100644 --- a/ext/opcache/tests/jit/inc_018.phpt +++ b/ext/opcache/tests/jit/inc_018.phpt @@ -18,4 +18,5 @@ function foo() { var_dump(foo()); ?> --EXPECT-- +Warning: Increment on bool has no effect in Unknown on line 0 bool(false) diff --git a/ext/opcache/tests/jit/inc_022.phpt b/ext/opcache/tests/jit/inc_022.phpt index 75971cff6c2e9..adddc189d0211 100644 --- a/ext/opcache/tests/jit/inc_022.phpt +++ b/ext/opcache/tests/jit/inc_022.phpt @@ -23,7 +23,8 @@ var_dump(inc(1.1)); var_dump(dec("5")); var_dump(dec(1.1)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "abd" int(6) float(2.1) diff --git a/ext/opcache/tests/jit/inc_023.phpt b/ext/opcache/tests/jit/inc_023.phpt index 6ec64e057e503..af97c2b5b7de3 100644 --- a/ext/opcache/tests/jit/inc_023.phpt +++ b/ext/opcache/tests/jit/inc_023.phpt @@ -19,6 +19,13 @@ $test->prop = "a"; var_dump(++$test->prop); var_dump(--$test->prop); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Warning: Decrement on non-numeric string has no effect in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(1) "c" + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(1) "c" diff --git a/ext/opcache/tests/jit/inc_024.phpt b/ext/opcache/tests/jit/inc_024.phpt index 8d2e361c0dc7f..cbc7375316c45 100644 --- a/ext/opcache/tests/jit/inc_024.phpt +++ b/ext/opcache/tests/jit/inc_024.phpt @@ -23,6 +23,53 @@ function test($b) { } test("0"); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Warning: Decrement on non-numeric string has no effect in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(5) "-INF0" string(260) "0-2-12-112-1112-11112-111112-1111112-11111112-111111112-1111111112-11111111112-111111111112-1111111111112-11111111111112-111111111111112-1111111111111112-11111111111111112-111111111111111112-1111111111111111112-1.1111111111111E+20-1.1111111111111E+191-ING-INF1" diff --git a/ext/opcache/tests/opt/sccp_035.phpt b/ext/opcache/tests/opt/sccp_035.phpt index 86965b13b5f3d..259df9ffb1495 100644 --- a/ext/opcache/tests/opt/sccp_035.phpt +++ b/ext/opcache/tests/opt/sccp_035.phpt @@ -14,4 +14,5 @@ function test() { ?> DONE --EXPECT-- +Deprecated: Decrement on empty string is deprecated as non-numeric in Unknown on line 0 DONE diff --git a/ext/opcache/tests/opt/sccp_038.phpt b/ext/opcache/tests/opt/sccp_038.phpt index fdf663e87c362..810dc4c8b4ed5 100644 --- a/ext/opcache/tests/opt/sccp_038.phpt +++ b/ext/opcache/tests/opt/sccp_038.phpt @@ -15,4 +15,5 @@ foo(); ?> DONE --EXPECT-- +Deprecated: Increment on non-numeric string is deprecated in Unknown on line 0 DONE diff --git a/tests/lang/operators/postdec_variationStr.phpt b/tests/lang/operators/postdec_variationStr.phpt index cb452ccba9e66..1114fd45ad85f 100644 --- a/tests/lang/operators/postdec_variationStr.phpt +++ b/tests/lang/operators/postdec_variationStr.phpt @@ -16,7 +16,7 @@ foreach ($strVals as $strVal) { } ?> ---EXPECT-- +--EXPECTF-- --- testing: '0' --- int(-1) --- testing: '65' --- @@ -28,20 +28,36 @@ float(0.19999999999999996) --- testing: '-7.7' --- float(-8.7) --- testing: 'abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(3) "abc" --- testing: '123abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(6) "123abc" --- testing: '123e5' --- float(12299999) --- testing: '123e5xyz' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(8) "123e5xyz" --- testing: ' 123abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(7) " 123abc" --- testing: '123 abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(7) "123 abc" --- testing: '123abc ' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(7) "123abc " --- testing: '3.4a' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(4) "3.4a" --- testing: 'a5.9' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(4) "a5.9" diff --git a/tests/lang/operators/postinc_variationStr.phpt b/tests/lang/operators/postinc_variationStr.phpt index 800b5c24552f7..3de057dfae4a6 100644 --- a/tests/lang/operators/postinc_variationStr.phpt +++ b/tests/lang/operators/postinc_variationStr.phpt @@ -16,7 +16,7 @@ foreach ($strVals as $strVal) { } ?> ---EXPECT-- +--EXPECTF-- --- testing: '0' --- int(1) --- testing: '65' --- @@ -28,20 +28,36 @@ float(2.2) --- testing: '-7.7' --- float(-6.7) --- testing: 'abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "abd" --- testing: '123abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(6) "123abd" --- testing: '123e5' --- float(12300001) --- testing: '123e5xyz' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(8) "123e5xza" --- testing: ' 123abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(7) " 123abd" --- testing: '123 abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(7) "123 abd" --- testing: '123abc ' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(7) "123abc " --- testing: '3.4a' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "3.4b" --- testing: 'a5.9' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "a5.0" diff --git a/tests/lang/operators/predec_variationStr.phpt b/tests/lang/operators/predec_variationStr.phpt index ebbb6c9de3499..01f99e341ddbb 100644 --- a/tests/lang/operators/predec_variationStr.phpt +++ b/tests/lang/operators/predec_variationStr.phpt @@ -15,7 +15,7 @@ foreach ($strVals as $strVal) { } ?> ---EXPECT-- +--EXPECTF-- --- testing: '0' --- int(-1) --- testing: '65' --- @@ -27,20 +27,36 @@ float(0.19999999999999996) --- testing: '-7.7' --- float(-8.7) --- testing: 'abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(3) "abc" --- testing: '123abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(6) "123abc" --- testing: '123e5' --- float(12299999) --- testing: '123e5xyz' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(8) "123e5xyz" --- testing: ' 123abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(7) " 123abc" --- testing: '123 abc' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(7) "123 abc" --- testing: '123abc ' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(7) "123abc " --- testing: '3.4a' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(4) "3.4a" --- testing: 'a5.9' --- + +Warning: Decrement on non-numeric string has no effect in %s on line %d string(4) "a5.9" diff --git a/tests/lang/operators/preinc_variationStr.phpt b/tests/lang/operators/preinc_variationStr.phpt index abb3663889c1a..9378aba78d4f3 100644 --- a/tests/lang/operators/preinc_variationStr.phpt +++ b/tests/lang/operators/preinc_variationStr.phpt @@ -16,7 +16,7 @@ foreach ($strVals as $strVal) { } ?> ---EXPECT-- +--EXPECTF-- --- testing: '0' --- int(1) --- testing: '65' --- @@ -28,38 +28,72 @@ float(2.2) --- testing: '-7.7' --- float(-6.7) --- testing: 'abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "abd" --- testing: '123abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(6) "123abd" --- testing: '123e5' --- float(12300001) --- testing: '123e5xyz' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(8) "123e5xza" --- testing: ' 123abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(7) " 123abd" --- testing: '123 abc' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(7) "123 abd" --- testing: '123abc ' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(7) "123abc " --- testing: '3.4a' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "3.4b" --- testing: 'a5.9' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "a5.0" --- testing: 'z' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "aa" --- testing: 'az' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "ba" --- testing: 'zz' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "aaa" --- testing: 'Z' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "AA" --- testing: 'AZ' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "BA" --- testing: 'ZZ' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "AAA" --- testing: '9z' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "10a" --- testing: '19z' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "20a" --- testing: '99z' --- + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "100a" From bac48a0293d33bf0238a91158742a7e77f98e4a7 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sat, 18 Jun 2022 15:12:20 +0100 Subject: [PATCH 04/23] Handle exceptions in Opcodes --- Zend/zend_vm_def.h | 12 ++++++++++++ Zend/zend_vm_execute.h | 24 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b7d98e55a001a..1745634fe1a01 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1500,6 +1500,9 @@ ZEND_VM_HELPER(zend_pre_inc_helper, VAR|CV, ANY) } } increment_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -1552,6 +1555,9 @@ ZEND_VM_HELPER(zend_pre_dec_helper, VAR|CV, ANY) } } decrement_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -1606,6 +1612,9 @@ ZEND_VM_HELPER(zend_post_inc_helper, VAR|CV, ANY) ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); increment_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); FREE_OP1(); @@ -1654,6 +1663,9 @@ ZEND_VM_HELPER(zend_post_dec_helper, VAR|CV, ANY) ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); decrement_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); FREE_OP1(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 56fdc55ea7404..d0c15e16b2289 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -21593,6 +21593,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help } } increment_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -21663,6 +21666,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help } } decrement_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -21735,6 +21741,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); increment_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -21783,6 +21792,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); decrement_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -38908,6 +38920,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_inc_help } } increment_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -38977,6 +38992,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_dec_help } } decrement_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { @@ -39048,6 +39066,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_inc_hel ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); increment_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); @@ -39095,6 +39116,9 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_dec_hel ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); decrement_function(var_ptr); + if (UNEXPECTED(EG(exception))) { + HANDLE_EXCEPTION(); + } } while (0); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); From 5e14fbb6537bdba7ac541d7b9adedb413db8b69f Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 13 Jan 2023 21:53:31 +0000 Subject: [PATCH 05/23] Add tests for in/decrement with castable numeric objects not implementing do_operation --- ..._with_castable_objects_no_subtraction.phpt | 76 ++++++++++ ...ent_with_castable_objects_no_addition.phpt | 76 ++++++++++ ext/zend_test/test.c | 141 ++++++++++++++++++ ext/zend_test/test.stub.php | 13 ++ ext/zend_test/test_arginfo.h | 84 ++++++++++- 5 files changed, 389 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt create mode 100644 Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt diff --git a/Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt b/Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt new file mode 100644 index 0000000000000..1887c06545bf2 --- /dev/null +++ b/Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt @@ -0,0 +1,76 @@ +--TEST-- +Decrementing objects which are castable to numeric types +--EXTENSIONS-- +zend_test +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($f - 1); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + var_dump($nl - 1); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + var_dump($nf - 1); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +/* Decrement */ +try { + $l--; + var_dump($l); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $f--; + var_dump($f); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $nl--; + var_dump($nl); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $nf--; + var_dump($nf); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Unsupported operand types: LongCastableNoOperations - int +Unsupported operand types: FloatCastableNoOperations - int +int(51) +float(57.3) +Cannot decrement LongCastableNoOperations +Cannot decrement FloatCastableNoOperations +Cannot decrement NumericCastableNoOperations +Cannot decrement NumericCastableNoOperations diff --git a/Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt b/Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt new file mode 100644 index 0000000000000..953682ca01a17 --- /dev/null +++ b/Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt @@ -0,0 +1,76 @@ +--TEST-- +Incrementing objects which are castable to numeric types +--EXTENSIONS-- +zend_test +--FILE-- +getMessage(), PHP_EOL; +} + +try { + var_dump($f + 1); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + var_dump($nl + 1); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + var_dump($nf + 1); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +/* Decrement */ +try { + $l++; + var_dump($l); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $f++; + var_dump($f); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $nl++; + var_dump($nl); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + $nf++; + var_dump($nf); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +Unsupported operand types: LongCastableNoOperations + int +Unsupported operand types: FloatCastableNoOperations + int +int(53) +float(59.3) +Cannot increment LongCastableNoOperations +Cannot increment FloatCastableNoOperations +Cannot increment NumericCastableNoOperations +Cannot increment NumericCastableNoOperations diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index aade7c5674f58..955be48c85490 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -939,6 +939,131 @@ PHP_METHOD(DoOperationNoCast, __construct) ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l); } +static zend_class_entry *long_castable_no_operation_ce; +static zend_object_handlers long_castable_no_operation_object_handlers; + +static zend_object* long_castable_no_operation_object_create_ex(zend_class_entry* ce, zend_long l) { + zend_object *obj = zend_objects_new(ce); + object_properties_init(obj, ce); + obj->handlers = &long_castable_no_operation_object_handlers; + ZVAL_LONG(OBJ_PROP_NUM(obj, 0), l); + return obj; +} + +static zend_object *long_castable_no_operation_object_create(zend_class_entry *ce) +{ + return long_castable_no_operation_object_create_ex(ce, 0); +} + +static inline void long_castable_no_operation_create(zval *target, zend_long l) +{ + ZVAL_OBJ(target, long_castable_no_operation_object_create_ex(long_castable_no_operation_ce, l)); +} + +static zend_result long_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) +{ + if (type == IS_LONG) { + ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0)); + return SUCCESS; + } + return FAILURE; +} + +PHP_METHOD(LongCastableNoOperations, __construct) +{ + zend_long l; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_LONG(l) + ZEND_PARSE_PARAMETERS_END(); + + ZVAL_LONG(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), l); +} + +static zend_class_entry *float_castable_no_operation_ce; +static zend_object_handlers float_castable_no_operation_object_handlers; + +static zend_object* float_castable_no_operation_object_create_ex(zend_class_entry* ce, double d) { + zend_object *obj = zend_objects_new(ce); + object_properties_init(obj, ce); + obj->handlers = &float_castable_no_operation_object_handlers; + ZVAL_DOUBLE(OBJ_PROP_NUM(obj, 0), d); + return obj; +} + +static zend_object *float_castable_no_operation_object_create(zend_class_entry *ce) +{ + return float_castable_no_operation_object_create_ex(ce, 0.0); +} + +static inline void float_castable_no_operation_create(zval *target, double d) +{ + ZVAL_OBJ(target, float_castable_no_operation_object_create_ex(float_castable_no_operation_ce, d)); +} + +static zend_result float_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) +{ + if (type == IS_DOUBLE) { + ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0)); + return SUCCESS; + } + return FAILURE; +} + +PHP_METHOD(FloatCastableNoOperations, __construct) +{ + double d; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_DOUBLE(d) + ZEND_PARSE_PARAMETERS_END(); + + ZVAL_DOUBLE(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), d); +} + +static zend_class_entry *numeric_castable_no_operation_ce; +static zend_object_handlers numeric_castable_no_operation_object_handlers; + +static zend_object* numeric_castable_no_operation_object_create_ex(zend_class_entry* ce, const zval *n) { + zend_object *obj = zend_objects_new(ce); + object_properties_init(obj, ce); + obj->handlers = &numeric_castable_no_operation_object_handlers; + ZVAL_COPY(OBJ_PROP_NUM(obj, 0), n); + return obj; +} + +static zend_object *numeric_castable_no_operation_object_create(zend_class_entry *ce) +{ + zval tmp; + ZVAL_LONG(&tmp, 0); + return numeric_castable_no_operation_object_create_ex(ce, &tmp); +} + +static inline void numeric_castable_no_operation_create(zval *target, const zval *n) +{ + ZVAL_OBJ(target, numeric_castable_no_operation_object_create_ex(numeric_castable_no_operation_ce, n)); +} + +static zend_result numeric_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) +{ + if (type == _IS_NUMBER) { + ZVAL_COPY(result, OBJ_PROP_NUM(obj, 0)); + return SUCCESS; + } + return FAILURE; +} + +PHP_METHOD(NumericCastableNoOperations, __construct) +{ + zval *n; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_NUMBER(n) + ZEND_PARSE_PARAMETERS_END(); + + ZVAL_COPY(OBJ_PROP_NUM(Z_OBJ_P(ZEND_THIS), 0), n); +} + PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.replace_zend_execute_ex", "0", PHP_INI_SYSTEM, OnUpdateBool, replace_zend_execute_ex, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.register_passes", "0", PHP_INI_SYSTEM, OnUpdateBool, register_passes, zend_zend_test_globals, zend_test_globals) @@ -1011,6 +1136,22 @@ PHP_MINIT_FUNCTION(zend_test) memcpy(&donc_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); donc_object_handlers.do_operation = donc_do_operation; + /* CastableNoOperation classes */ + long_castable_no_operation_ce = register_class_LongCastableNoOperations(); + long_castable_no_operation_ce->create_object = long_castable_no_operation_object_create; + memcpy(&long_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + long_castable_no_operation_object_handlers.cast_object = long_castable_no_operation_cast_object; + + float_castable_no_operation_ce = register_class_FloatCastableNoOperations(); + float_castable_no_operation_ce->create_object = float_castable_no_operation_object_create; + memcpy(&float_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + float_castable_no_operation_object_handlers.cast_object = float_castable_no_operation_cast_object; + + numeric_castable_no_operation_ce = register_class_NumericCastableNoOperations(); + numeric_castable_no_operation_ce->create_object = numeric_castable_no_operation_object_create; + memcpy(&numeric_castable_no_operation_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + numeric_castable_no_operation_object_handlers.cast_object = numeric_castable_no_operation_cast_object; + zend_register_functions(NULL, ext_function_legacy, NULL, EG(current_module)->type); // Loading via dl() not supported with the observer API diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php index 88d9f19883f88..62bdcb8bd52bf 100644 --- a/ext/zend_test/test.stub.php +++ b/ext/zend_test/test.stub.php @@ -132,6 +132,19 @@ final class DoOperationNoCast { public function __construct(int $val) {} } + final class LongCastableNoOperations { + private int $val; + public function __construct(int $val) {} + } + final class FloatCastableNoOperations { + private float $val; + public function __construct(float $val) {} + } + final class NumericCastableNoOperations { + private int|float $val; + public function __construct(int|float $val) {} + } + function zend_test_array_return(): array {} function zend_test_nullable_array_return(): null|array {} diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h index 6587b40e1e405..c47250ff27397 100644 --- a/ext/zend_test/test_arginfo.h +++ b/ext/zend_test/test_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 46e6d8be5504acb6ecbb722da4fabfcea4e8a354 */ + * Stub hash: 3c1b17bbb7ef84e036a251c685bd7fd79fe9f434 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() @@ -189,6 +189,16 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DoOperationNoCast___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, val, IS_LONG, 0) ZEND_END_ARG_INFO() +#define arginfo_class_LongCastableNoOperations___construct arginfo_class_DoOperationNoCast___construct + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_FloatCastableNoOperations___construct, 0, 0, 1) + ZEND_ARG_TYPE_INFO(0, val, IS_DOUBLE, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_NumericCastableNoOperations___construct, 0, 0, 1) + ZEND_ARG_TYPE_MASK(0, val, MAY_BE_LONG|MAY_BE_DOUBLE, NULL) +ZEND_END_ARG_INFO() + #if (PHP_VERSION_ID >= 80100) ZEND_BEGIN_ARG_WITH_TENTATIVE_RETURN_TYPE_INFO_EX(arginfo_class_ZendTestNS_Foo_method, 0, 0, IS_LONG, 0) #else @@ -260,6 +270,9 @@ static ZEND_METHOD(ZendTestChildClassWithMethodWithParameterAttribute, override) static ZEND_METHOD(ZendTestForbidDynamicCall, call); static ZEND_METHOD(ZendTestForbidDynamicCall, callStatic); static ZEND_METHOD(DoOperationNoCast, __construct); +static ZEND_METHOD(LongCastableNoOperations, __construct); +static ZEND_METHOD(FloatCastableNoOperations, __construct); +static ZEND_METHOD(NumericCastableNoOperations, __construct); static ZEND_METHOD(ZendTestNS_Foo, method); static ZEND_METHOD(ZendTestNS_UnlikelyCompileError, method); static ZEND_METHOD(ZendTestNS2_Foo, method); @@ -403,6 +416,24 @@ static const zend_function_entry class_DoOperationNoCast_methods[] = { }; +static const zend_function_entry class_LongCastableNoOperations_methods[] = { + ZEND_ME(LongCastableNoOperations, __construct, arginfo_class_LongCastableNoOperations___construct, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + +static const zend_function_entry class_FloatCastableNoOperations_methods[] = { + ZEND_ME(FloatCastableNoOperations, __construct, arginfo_class_FloatCastableNoOperations___construct, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + +static const zend_function_entry class_NumericCastableNoOperations_methods[] = { + ZEND_ME(NumericCastableNoOperations, __construct, arginfo_class_NumericCastableNoOperations___construct, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + + static const zend_function_entry class_ZendTestNS_Foo_methods[] = { ZEND_ME(ZendTestNS_Foo, method, arginfo_class_ZendTestNS_Foo_method, ZEND_ACC_PUBLIC) ZEND_FE_END @@ -792,6 +823,57 @@ static zend_class_entry *register_class_DoOperationNoCast(void) return class_entry; } +static zend_class_entry *register_class_LongCastableNoOperations(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "LongCastableNoOperations", class_LongCastableNoOperations_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_FINAL; + + zval property_val_default_value; + ZVAL_UNDEF(&property_val_default_value); + zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, 1); + zend_declare_typed_property(class_entry, property_val_name, &property_val_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG)); + zend_string_release(property_val_name); + + return class_entry; +} + +static zend_class_entry *register_class_FloatCastableNoOperations(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "FloatCastableNoOperations", class_FloatCastableNoOperations_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_FINAL; + + zval property_val_default_value; + ZVAL_UNDEF(&property_val_default_value); + zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, 1); + zend_declare_typed_property(class_entry, property_val_name, &property_val_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_DOUBLE)); + zend_string_release(property_val_name); + + return class_entry; +} + +static zend_class_entry *register_class_NumericCastableNoOperations(void) +{ + zend_class_entry ce, *class_entry; + + INIT_CLASS_ENTRY(ce, "NumericCastableNoOperations", class_NumericCastableNoOperations_methods); + class_entry = zend_register_internal_class_ex(&ce, NULL); + class_entry->ce_flags |= ZEND_ACC_FINAL; + + zval property_val_default_value; + ZVAL_UNDEF(&property_val_default_value); + zend_string *property_val_name = zend_string_init("val", sizeof("val") - 1, 1); + zend_declare_typed_property(class_entry, property_val_name, &property_val_default_value, ZEND_ACC_PRIVATE, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_LONG|MAY_BE_DOUBLE)); + zend_string_release(property_val_name); + + return class_entry; +} + static zend_class_entry *register_class_ZendTestNS_Foo(void) { zend_class_entry ce, *class_entry; From 11fcfd1f7d0a46342652452d7616b388f715e36c Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sat, 14 Jan 2023 14:33:54 +0000 Subject: [PATCH 06/23] Update messages to reflect 0.2 RFC version --- .../in-de-crement/incdec_bool_exception.phpt | 8 ++++---- Zend/tests/in-de-crement/incdec_strings.phpt | 14 +++++++------- .../in-de-crement/incdec_strings_exception.phpt | 14 +++++++------- Zend/tests/in-de-crement/incdec_types.phpt | 12 +++++++----- Zend/tests/in-de-crement/incdec_undef.phpt | 3 ++- Zend/zend_operators.c | 14 ++++++++++---- ext/opcache/tests/jit/inc_017.phpt | 2 +- ext/opcache/tests/jit/inc_018.phpt | 2 +- ext/opcache/tests/jit/inc_023.phpt | 4 ++-- ext/opcache/tests/jit/inc_024.phpt | 2 +- ext/opcache/tests/jit/reg_alloc_014.phpt | 6 +++++- tests/lang/operators/postdec_variationStr.phpt | 16 ++++++++-------- tests/lang/operators/predec_variationStr.phpt | 16 ++++++++-------- 13 files changed, 63 insertions(+), 50 deletions(-) diff --git a/Zend/tests/in-de-crement/incdec_bool_exception.phpt b/Zend/tests/in-de-crement/incdec_bool_exception.phpt index 5071939ea62ab..f819af1e23956 100644 --- a/Zend/tests/in-de-crement/incdec_bool_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_bool_exception.phpt @@ -22,7 +22,7 @@ foreach ($values as $value) { } ?> --EXPECT-- -Increment on type bool has no effect -Decrement on type bool has no effect -Increment on type bool has no effect -Decrement on type bool has no effect +Increment on type bool has no effect, this will change in the next major version of PHP +Decrement on type bool has no effect, this will change in the next major version of PHP +Increment on type bool has no effect, this will change in the next major version of PHP +Decrement on type bool has no effect, this will change in the next major version of PHP diff --git a/Zend/tests/in-de-crement/incdec_strings.phpt b/Zend/tests/in-de-crement/incdec_strings.phpt index 75a43d2d8fdfe..a4eb0d21d35fd 100644 --- a/Zend/tests/in-de-crement/incdec_strings.phpt +++ b/Zend/tests/in-de-crement/incdec_strings.phpt @@ -100,7 +100,7 @@ Deprecated: Decrement on empty string is deprecated as non-numeric in %s on line Result value:int(-1) Initial value:string(1) " " -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(-1) @@ -110,25 +110,25 @@ Initial value:string(4) "1e10" Result value:float(9999999999) Initial value:string(4) "199A" -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(4) "199A" Initial value:string(4) "A199" -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(4) "A199" Initial value:string(4) "199Z" -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(4) "199Z" Initial value:string(4) "Z199" -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(4) "Z199" Initial value:string(11) "Hello world" -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(11) "Hello world" Initial value:string(4) "🐘" -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(4) "🐘" diff --git a/Zend/tests/in-de-crement/incdec_strings_exception.phpt b/Zend/tests/in-de-crement/incdec_strings_exception.phpt index b8b5d865bba2d..af2bb72c0c736 100644 --- a/Zend/tests/in-de-crement/incdec_strings_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_strings_exception.phpt @@ -47,29 +47,29 @@ Deprecated: Decrement on empty string is deprecated as non-numeric string(0) "" Deprecated: Increment on non-numeric string is deprecated string(1) " " -Warning: Decrement on non-numeric string has no effect +Deprecated: Decrement on non-numeric string has no effect and is deprecated string(1) " " Deprecated: Increment on non-numeric string is deprecated string(4) "199A" -Warning: Decrement on non-numeric string has no effect +Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "199A" Deprecated: Increment on non-numeric string is deprecated string(4) "A199" -Warning: Decrement on non-numeric string has no effect +Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "A199" Deprecated: Increment on non-numeric string is deprecated string(4) "199Z" -Warning: Decrement on non-numeric string has no effect +Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "199Z" Deprecated: Increment on non-numeric string is deprecated string(4) "Z199" -Warning: Decrement on non-numeric string has no effect +Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "Z199" Deprecated: Increment on non-numeric string is deprecated string(11) "Hello world" -Warning: Decrement on non-numeric string has no effect +Deprecated: Decrement on non-numeric string has no effect and is deprecated string(11) "Hello world" Deprecated: Increment on non-numeric string is deprecated string(4) "🐘" -Warning: Decrement on non-numeric string has no effect +Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "🐘" diff --git a/Zend/tests/in-de-crement/incdec_types.phpt b/Zend/tests/in-de-crement/incdec_types.phpt index a61335a4ae175..cee3277565a39 100644 --- a/Zend/tests/in-de-crement/incdec_types.phpt +++ b/Zend/tests/in-de-crement/incdec_types.phpt @@ -51,11 +51,11 @@ Initial value:NULL Result value:int(1) Initial value:bool(false) -Warning: Increment on type bool has no effect in %s on line %d +Warning: Increment on type bool has no effect, this will change in the next major version of PHP in %s on line %d Result value:bool(false) Initial value:bool(true) -Warning: Increment on type bool has no effect in %s on line %d +Warning: Increment on type bool has no effect, this will change in the next major version of PHP in %s on line %d Result value:bool(true) Initial value:int(0) Result value:int(1) @@ -73,14 +73,16 @@ Initial value:string(1) "0" Result value:int(1) Using decrement: Initial value:NULL + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d Result value:NULL Initial value:bool(false) -Warning: Decrement on type bool has no effect in %s on line %d +Warning: Decrement on type bool has no effect, this will change in the next major version of PHP in %s on line %d Result value:bool(false) Initial value:bool(true) -Warning: Decrement on type bool has no effect in %s on line %d +Warning: Decrement on type bool has no effect, this will change in the next major version of PHP in %s on line %d Result value:bool(true) Initial value:int(0) Result value:int(-1) @@ -92,7 +94,7 @@ Deprecated: Decrement on empty string is deprecated as non-numeric in %s on line Result value:int(-1) Initial value:string(1) " " -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(-1) diff --git a/Zend/tests/in-de-crement/incdec_undef.phpt b/Zend/tests/in-de-crement/incdec_undef.phpt index c3a18cb53529a..db560e31c99f3 100644 --- a/Zend/tests/in-de-crement/incdec_undef.phpt +++ b/Zend/tests/in-de-crement/incdec_undef.phpt @@ -4,7 +4,6 @@ Inc/dec undef var with error handler --EXPECT-- Undefined variable $x +Decrement on type null has no effect, this will change in the next major version of PHP NULL Undefined variable $x NULL Undefined variable $x +Decrement on type null has no effect, this will change in the next major version of PHP NULL Undefined variable $x int(1) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 42806c393d9bb..8353d80372f56 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2629,7 +2629,7 @@ ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1) /* {{{ */ break; case IS_FALSE: case IS_TRUE: - zend_error(E_WARNING, "Increment on type bool has no effect"); + zend_error(E_WARNING, "Increment on type bool has no effect, this will change in the next major version of PHP"); break; case IS_REFERENCE: op1 = Z_REFVAL_P(op1); @@ -2691,18 +2691,24 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ ZVAL_DOUBLE(op1, dval - 1); break; default: - zend_error(E_WARNING, "Decrement on non-numeric string has no effect"); + zend_error(E_DEPRECATED, "Decrement on non-numeric string has no effect and is deprecated"); if (EG(exception)) { return FAILURE; } } break; case IS_NULL: - /* Do nothing. */ + zend_error(E_WARNING, "Decrement on type null has no effect, this will change in the next major version of PHP"); + if (EG(exception)) { + return FAILURE; + } break; case IS_FALSE: case IS_TRUE: - zend_error(E_WARNING, "Decrement on type bool has no effect"); + zend_error(E_WARNING, "Decrement on type bool has no effect, this will change in the next major version of PHP"); + if (EG(exception)) { + return FAILURE; + } break; case IS_REFERENCE: op1 = Z_REFVAL_P(op1); diff --git a/ext/opcache/tests/jit/inc_017.phpt b/ext/opcache/tests/jit/inc_017.phpt index a9cabcd7ad3d3..ab9b8cc3571fd 100644 --- a/ext/opcache/tests/jit/inc_017.phpt +++ b/ext/opcache/tests/jit/inc_017.phpt @@ -18,5 +18,5 @@ function foo() { var_dump(foo()); ?> --EXPECT-- -Warning: Increment on bool has no effect in Unknown on line 0 +Warning: Increment on type bool has no effect, this will change in the next major version of PHP in Unknown on line 0 bool(true) diff --git a/ext/opcache/tests/jit/inc_018.phpt b/ext/opcache/tests/jit/inc_018.phpt index 895136e0f2501..9fc50904ef521 100644 --- a/ext/opcache/tests/jit/inc_018.phpt +++ b/ext/opcache/tests/jit/inc_018.phpt @@ -18,5 +18,5 @@ function foo() { var_dump(foo()); ?> --EXPECT-- -Warning: Increment on bool has no effect in Unknown on line 0 +Warning: Increment on type bool has no effect, this will change in the next major version of PHP in Unknown on line 0 bool(false) diff --git a/ext/opcache/tests/jit/inc_023.phpt b/ext/opcache/tests/jit/inc_023.phpt index af97c2b5b7de3..292c7a921d1a5 100644 --- a/ext/opcache/tests/jit/inc_023.phpt +++ b/ext/opcache/tests/jit/inc_023.phpt @@ -22,10 +22,10 @@ var_dump(--$test->prop); --EXPECTF-- Deprecated: Increment on non-numeric string is deprecated in %s on line %d -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(1) "c" -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d string(1) "c" diff --git a/ext/opcache/tests/jit/inc_024.phpt b/ext/opcache/tests/jit/inc_024.phpt index cbc7375316c45..10d87febe5fef 100644 --- a/ext/opcache/tests/jit/inc_024.phpt +++ b/ext/opcache/tests/jit/inc_024.phpt @@ -68,7 +68,7 @@ Deprecated: Increment on non-numeric string is deprecated in %s on line %d Deprecated: Increment on non-numeric string is deprecated in %s on line %d -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(5) "-INF0" diff --git a/ext/opcache/tests/jit/reg_alloc_014.phpt b/ext/opcache/tests/jit/reg_alloc_014.phpt index 03b7ae0667c1f..ec048612c38f6 100644 --- a/ext/opcache/tests/jit/reg_alloc_014.phpt +++ b/ext/opcache/tests/jit/reg_alloc_014.phpt @@ -18,4 +18,8 @@ foo(); DONE --EXPECTF-- Warning: Undefined variable $a in %sreg_alloc_014.php on line 4 -DONE \ No newline at end of file + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %sreg_alloc_014.php on line 4 + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %sreg_alloc_014.php on line 4 +DONE diff --git a/tests/lang/operators/postdec_variationStr.phpt b/tests/lang/operators/postdec_variationStr.phpt index 1114fd45ad85f..25e5c646067a6 100644 --- a/tests/lang/operators/postdec_variationStr.phpt +++ b/tests/lang/operators/postdec_variationStr.phpt @@ -29,35 +29,35 @@ float(0.19999999999999996) float(-8.7) --- testing: 'abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(3) "abc" --- testing: '123abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(6) "123abc" --- testing: '123e5' --- float(12299999) --- testing: '123e5xyz' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(8) "123e5xyz" --- testing: ' 123abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(7) " 123abc" --- testing: '123 abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(7) "123 abc" --- testing: '123abc ' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(7) "123abc " --- testing: '3.4a' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(4) "3.4a" --- testing: 'a5.9' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(4) "a5.9" diff --git a/tests/lang/operators/predec_variationStr.phpt b/tests/lang/operators/predec_variationStr.phpt index 01f99e341ddbb..a98419690880c 100644 --- a/tests/lang/operators/predec_variationStr.phpt +++ b/tests/lang/operators/predec_variationStr.phpt @@ -28,35 +28,35 @@ float(0.19999999999999996) float(-8.7) --- testing: 'abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(3) "abc" --- testing: '123abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(6) "123abc" --- testing: '123e5' --- float(12299999) --- testing: '123e5xyz' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(8) "123e5xyz" --- testing: ' 123abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(7) " 123abc" --- testing: '123 abc' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(7) "123 abc" --- testing: '123abc ' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(7) "123abc " --- testing: '3.4a' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(4) "3.4a" --- testing: 'a5.9' --- -Warning: Decrement on non-numeric string has no effect in %s on line %d +Deprecated: Decrement on non-numeric string has no effect and is deprecated %s on line %d string(4) "a5.9" From fd2b76f47b3fada2c4dc266726c55652b4d6bb21 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sat, 14 Jan 2023 14:44:31 +0000 Subject: [PATCH 07/23] Add support to ++/-- for objects castable to _IS_NUMBER --- ..._with_castable_objects_no_subtraction.phpt | 4 ++-- ...ent_with_castable_objects_no_addition.phpt | 4 ++-- Zend/zend_operators.c | 20 +++++++++++++++++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt b/Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt index 1887c06545bf2..21b4a9b01684a 100644 --- a/Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt +++ b/Zend/tests/in-de-crement/decrement_with_castable_objects_no_subtraction.phpt @@ -72,5 +72,5 @@ int(51) float(57.3) Cannot decrement LongCastableNoOperations Cannot decrement FloatCastableNoOperations -Cannot decrement NumericCastableNoOperations -Cannot decrement NumericCastableNoOperations +int(51) +float(57.3) diff --git a/Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt b/Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt index 953682ca01a17..cf08055383ed8 100644 --- a/Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt +++ b/Zend/tests/in-de-crement/increment_with_castable_objects_no_addition.phpt @@ -72,5 +72,5 @@ int(53) float(59.3) Cannot increment LongCastableNoOperations Cannot increment FloatCastableNoOperations -Cannot increment NumericCastableNoOperations -Cannot increment NumericCastableNoOperations +int(53) +float(59.3) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 8353d80372f56..1e1b94ad1c79b 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2634,7 +2634,7 @@ ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1) /* {{{ */ case IS_REFERENCE: op1 = Z_REFVAL_P(op1); goto try_again; - case IS_OBJECT: + case IS_OBJECT: { if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; ZVAL_LONG(&op2, 1); @@ -2642,7 +2642,15 @@ ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1) /* {{{ */ return SUCCESS; } } + zval tmp; + if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp, _IS_NUMBER) == SUCCESS) { + ZEND_ASSERT(Z_TYPE(tmp) == IS_LONG || Z_TYPE(tmp) == IS_DOUBLE); + zval_ptr_dtor(op1); + ZVAL_COPY(op1, &tmp); + goto try_again; + } ZEND_FALLTHROUGH; + } case IS_RESOURCE: case IS_ARRAY: zend_type_error("Cannot increment %s", zend_zval_value_name(op1)); @@ -2713,7 +2721,7 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ case IS_REFERENCE: op1 = Z_REFVAL_P(op1); goto try_again; - case IS_OBJECT: + case IS_OBJECT: { if (Z_OBJ_HANDLER_P(op1, do_operation)) { zval op2; ZVAL_LONG(&op2, 1); @@ -2721,7 +2729,15 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ return SUCCESS; } } + zval tmp; + if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp, _IS_NUMBER) == SUCCESS) { + ZEND_ASSERT(Z_TYPE(tmp) == IS_LONG || Z_TYPE(tmp) == IS_DOUBLE); + zval_ptr_dtor(op1); + ZVAL_COPY(op1, &tmp); + goto try_again; + } ZEND_FALLTHROUGH; + } case IS_RESOURCE: case IS_ARRAY: zend_type_error("Cannot decrement %s", zend_zval_value_name(op1)); From ba6956fb724f490e9185f5346d36ee9489dfdd5e Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 17 Jan 2023 15:34:25 +0000 Subject: [PATCH 08/23] Amend tests --- Zend/tests/027.phpt | 4 +- Zend/tests/bug71300.phpt | 15 + Zend/tests/enum/backed-from-unknown-hash.phpt | 3 +- .../enum/backed-tryFrom-unknown-hash.phpt | 3 +- Zend/tests/operator_unsupported_types.phpt | 2 + Zend/tests/remove_predecessor_of_pi_node.phpt | 2 + Zend/tests/temporary_cleaning_013.phpt | 2 + Zend/tests/unreachable_phi_cycle.phpt | 2 + ext/ffi/tests/025.phpt | 2 + ext/reflection/tests/bug48336.phpt | 4 +- ext/reflection/tests/traits004.phpt | 3 +- ext/reflection/tests/traits005.phpt | 3 +- ext/standard/tests/array/array_combine.phpt | 261 ++++++++++-------- 13 files changed, 183 insertions(+), 123 deletions(-) diff --git a/Zend/tests/027.phpt b/Zend/tests/027.phpt index a862d689e1a84..3706b2ddc63d9 100644 --- a/Zend/tests/027.phpt +++ b/Zend/tests/027.phpt @@ -17,6 +17,8 @@ $strtoupper = 'strtolower'; var_dump(${${++$a}}('FOO') == 'foo'); ?> ---EXPECT-- +--EXPECTF-- bool(true) + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d bool(true) diff --git a/Zend/tests/bug71300.phpt b/Zend/tests/bug71300.phpt index 40734b054933b..15d4f18d4abf0 100644 --- a/Zend/tests/bug71300.phpt +++ b/Zend/tests/bug71300.phpt @@ -22,7 +22,22 @@ function test2() { var_dump(test2()); ?> --EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "test" +Deprecated: Increment on non-numeric string is deprecated in %s on line %d + Warning: Array to string conversion in %s on line %d string(9) "Arraytest" diff --git a/Zend/tests/enum/backed-from-unknown-hash.phpt b/Zend/tests/enum/backed-from-unknown-hash.phpt index eb5938d0d6532..3c439ab0320b3 100644 --- a/Zend/tests/enum/backed-from-unknown-hash.phpt +++ b/Zend/tests/enum/backed-from-unknown-hash.phpt @@ -13,5 +13,6 @@ $s++; var_dump(Foo::from($s)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated in %s on line %d enum(Foo::Bar) diff --git a/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt b/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt index 80ffe1dc3908e..fe02fdc113b3a 100644 --- a/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt +++ b/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt @@ -13,5 +13,6 @@ $s++; var_dump(Foo::tryFrom($s)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Increment on non-numeric string is deprecated in %s on line %d enum(Foo::Bar) diff --git a/Zend/tests/operator_unsupported_types.phpt b/Zend/tests/operator_unsupported_types.phpt index c90f0e374ab56..3a3b8c0e3bdf3 100644 --- a/Zend/tests/operator_unsupported_types.phpt +++ b/Zend/tests/operator_unsupported_types.phpt @@ -2104,5 +2104,7 @@ Cannot increment stdClass Cannot decrement stdClass Cannot increment resource Cannot decrement resource +Warning: Increment on non-numeric string is deprecated No error for fop++ +Warning: Decrement on non-numeric string has no effect and is deprecated No error for foo-- diff --git a/Zend/tests/remove_predecessor_of_pi_node.phpt b/Zend/tests/remove_predecessor_of_pi_node.phpt index 6231f08b3f626..d33d8dc235768 100644 --- a/Zend/tests/remove_predecessor_of_pi_node.phpt +++ b/Zend/tests/remove_predecessor_of_pi_node.phpt @@ -12,3 +12,5 @@ test(); ?> --EXPECTF-- Warning: Undefined variable $n in %s on line %d + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d diff --git a/Zend/tests/temporary_cleaning_013.phpt b/Zend/tests/temporary_cleaning_013.phpt index e5f4b73bb14a2..3a6acf9c99df9 100644 --- a/Zend/tests/temporary_cleaning_013.phpt +++ b/Zend/tests/temporary_cleaning_013.phpt @@ -320,5 +320,7 @@ caught Exception 27 caught Exception 28 caught Exception 29 caught Exception 30 + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d caught Exception 31 caught Exception 32 diff --git a/Zend/tests/unreachable_phi_cycle.phpt b/Zend/tests/unreachable_phi_cycle.phpt index 84bfec214bb85..a8f4f145f0cb8 100644 --- a/Zend/tests/unreachable_phi_cycle.phpt +++ b/Zend/tests/unreachable_phi_cycle.phpt @@ -13,3 +13,5 @@ test(); ?> --EXPECTF-- Warning: Undefined variable $i in %s on line %d + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d diff --git a/ext/ffi/tests/025.phpt b/ext/ffi/tests/025.phpt index ba1e75e223f0d..2e381658dd32d 100644 --- a/ext/ffi/tests/025.phpt +++ b/ext/ffi/tests/025.phpt @@ -37,6 +37,8 @@ object(FFI\CData:char)#%d (1) { ["cdata"]=> string(1) "a" } + +Deprecated: Increment on non-numeric string is deprecated in %s on line %d object(FFI\CData:char)#%d (1) { ["cdata"]=> string(1) "b" diff --git a/ext/reflection/tests/bug48336.phpt b/ext/reflection/tests/bug48336.phpt index ee90675f0c5d6..a7d441c1cb3fe 100644 --- a/ext/reflection/tests/bug48336.phpt +++ b/ext/reflection/tests/bug48336.phpt @@ -23,8 +23,8 @@ class F extends E { static protected $prop; } -$class = 'A'; -for($class = 'A'; $class <= 'F'; $class ++) { +$classes = ['A', 'B', 'C', 'D', 'E', 'F']; +foreach ($classes as $class) { print($class.' => '); try { $rp = new ReflectionProperty($class, 'prop'); diff --git a/ext/reflection/tests/traits004.phpt b/ext/reflection/tests/traits004.phpt index 0feed127d9928..da65bfa9b3843 100644 --- a/ext/reflection/tests/traits004.phpt +++ b/ext/reflection/tests/traits004.phpt @@ -9,7 +9,8 @@ class C1 { } class C2 { use T1; } class C3 { use T1; use T2; } -for ($c = "C1"; $c <= "C3"; $c++) { +$classes = ['C1', 'C2', 'C3']; +foreach ($classes as $c) { echo "class $c:\n"; $r = new ReflectionClass($c); var_dump($r->getTraitNames()); diff --git a/ext/reflection/tests/traits005.phpt b/ext/reflection/tests/traits005.phpt index fbc917eafce03..ef218608a382c 100644 --- a/ext/reflection/tests/traits005.phpt +++ b/ext/reflection/tests/traits005.phpt @@ -9,7 +9,8 @@ class C2 { use T1; } class C3 { use T1 { m1 as a1; } } class C4 { use T1 { m1 as a1; m2 as a2; } } -for ($c = "C1"; $c <= "C4"; $c++) { +$classes = ['C1', 'C2', 'C3', 'C4']; +foreach ($classes as $c) { echo "class $c:\n"; $r = new ReflectionClass($c); var_dump($r->getTraitAliases()); diff --git a/ext/standard/tests/array/array_combine.phpt b/ext/standard/tests/array/array_combine.phpt index b1b707aed6795..5bdf9cd28b81e 100644 --- a/ext/standard/tests/array/array_combine.phpt +++ b/ext/standard/tests/array/array_combine.phpt @@ -2,121 +2,150 @@ basic array_combine test --FILE-- --EXPECT-- -Array -( - [green] => green - [red] => red - [yellow] => yellow -) -Array -( - [green] => 1 - [red] => 2 - [yellow] => 3 -) -Array -( - [green] => 0 - [red] => 1 - [yellow] => 2 -) -Array -( - [green] => 1 - [red] => - [yellow] => -) -Array -( - [1] => green - [2] => red - [3] => yellow -) -Array -( - [1] => 1 - [2] => 2 - [3] => 3 -) -Array -( - [1] => 0 - [2] => 1 - [3] => 2 -) -Array -( - [1] => 1 - [2] => - [3] => -) -Array -( - [0] => green - [1] => red - [2] => yellow -) -Array -( - [0] => 1 - [1] => 2 - [2] => 3 -) -Array -( - [0] => 0 - [1] => 1 - [2] => 2 -) -Array -( - [0] => 1 - [1] => - [2] => -) -Array -( - [1] => green - [] => yellow -) -Array -( - [1] => 1 - [] => 3 -) -Array -( - [1] => 0 - [] => 2 -) -Array -( - [1] => 1 - [] => -) +array(3) { + ["green"]=> + string(5) "green" + ["red"]=> + string(3) "red" + ["yellow"]=> + string(6) "yellow" +} +array(3) { + ["green"]=> + string(1) "1" + ["red"]=> + string(1) "2" + ["yellow"]=> + string(1) "3" +} +array(3) { + ["green"]=> + int(0) + ["red"]=> + int(1) + ["yellow"]=> + int(2) +} +array(3) { + ["green"]=> + bool(true) + ["red"]=> + bool(false) + ["yellow"]=> + NULL +} +array(3) { + [1]=> + string(5) "green" + [2]=> + string(3) "red" + [3]=> + string(6) "yellow" +} +array(3) { + [1]=> + string(1) "1" + [2]=> + string(1) "2" + [3]=> + string(1) "3" +} +array(3) { + [1]=> + int(0) + [2]=> + int(1) + [3]=> + int(2) +} +array(3) { + [1]=> + bool(true) + [2]=> + bool(false) + [3]=> + NULL +} +array(3) { + [0]=> + string(5) "green" + [1]=> + string(3) "red" + [2]=> + string(6) "yellow" +} +array(3) { + [0]=> + string(1) "1" + [1]=> + string(1) "2" + [2]=> + string(1) "3" +} +array(3) { + [0]=> + int(0) + [1]=> + int(1) + [2]=> + int(2) +} +array(3) { + [0]=> + bool(true) + [1]=> + bool(false) + [2]=> + NULL +} +array(2) { + [1]=> + string(5) "green" + [""]=> + string(6) "yellow" +} +array(2) { + [1]=> + string(1) "1" + [""]=> + string(1) "3" +} +array(2) { + [1]=> + int(0) + [""]=> + int(2) +} +array(2) { + [1]=> + bool(true) + [""]=> + NULL +} From a7c12f679784d9de0908c9fcffe4ea255bb78317 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Thu, 19 Jan 2023 16:53:11 +0000 Subject: [PATCH 09/23] Do not deprecate purely alphanumeric strings yet --- Zend/tests/027.phpt | 4 +- Zend/tests/bug71300.phpt | 15 --- Zend/tests/enum/backed-from-unknown-hash.phpt | 3 +- .../enum/backed-tryFrom-unknown-hash.phpt | 3 +- Zend/tests/in-de-crement/incdec_strings.phpt | 16 +-- .../incdec_strings_exception.phpt | 28 ++--- Zend/tests/in-de-crement/incdec_types.phpt | 4 +- .../string_increment_various.phpt | 107 ++++++++++++++++++ Zend/tests/operator_unsupported_types.phpt | 1 - Zend/tests/temporary_cleaning_013.phpt | 2 - Zend/zend_operators.c | 25 +++- ext/ffi/tests/025.phpt | 2 - ext/opcache/tests/bug77058.phpt | 2 + ext/opcache/tests/jit/inc_022.phpt | 3 +- ext/opcache/tests/jit/inc_023.phpt | 4 - ext/opcache/tests/jit/inc_024.phpt | 46 ++++---- ext/opcache/tests/opt/inference_016.phpt | 1 + ext/opcache/tests/opt/inference_019.phpt | 5 +- ext/opcache/tests/opt/sccp_038.phpt | 2 +- .../lang/operators/postinc_variationStr.phpt | 16 +-- tests/lang/operators/preinc_variationStr.phpt | 34 +----- 21 files changed, 190 insertions(+), 133 deletions(-) create mode 100644 Zend/tests/in-de-crement/string_increment_various.phpt diff --git a/Zend/tests/027.phpt b/Zend/tests/027.phpt index 3706b2ddc63d9..a862d689e1a84 100644 --- a/Zend/tests/027.phpt +++ b/Zend/tests/027.phpt @@ -17,8 +17,6 @@ $strtoupper = 'strtolower'; var_dump(${${++$a}}('FOO') == 'foo'); ?> ---EXPECTF-- +--EXPECT-- bool(true) - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d bool(true) diff --git a/Zend/tests/bug71300.phpt b/Zend/tests/bug71300.phpt index 15d4f18d4abf0..40734b054933b 100644 --- a/Zend/tests/bug71300.phpt +++ b/Zend/tests/bug71300.phpt @@ -22,22 +22,7 @@ function test2() { var_dump(test2()); ?> --EXPECTF-- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "test" -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - Warning: Array to string conversion in %s on line %d string(9) "Arraytest" diff --git a/Zend/tests/enum/backed-from-unknown-hash.phpt b/Zend/tests/enum/backed-from-unknown-hash.phpt index 3c439ab0320b3..eb5938d0d6532 100644 --- a/Zend/tests/enum/backed-from-unknown-hash.phpt +++ b/Zend/tests/enum/backed-from-unknown-hash.phpt @@ -13,6 +13,5 @@ $s++; var_dump(Foo::from($s)); ?> ---EXPECTF-- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +--EXPECT-- enum(Foo::Bar) diff --git a/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt b/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt index fe02fdc113b3a..80ffe1dc3908e 100644 --- a/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt +++ b/Zend/tests/enum/backed-tryFrom-unknown-hash.phpt @@ -13,6 +13,5 @@ $s++; var_dump(Foo::tryFrom($s)); ?> ---EXPECTF-- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +--EXPECT-- enum(Foo::Bar) diff --git a/Zend/tests/in-de-crement/incdec_strings.phpt b/Zend/tests/in-de-crement/incdec_strings.phpt index a4eb0d21d35fd..9df89536140b2 100644 --- a/Zend/tests/in-de-crement/incdec_strings.phpt +++ b/Zend/tests/in-de-crement/incdec_strings.phpt @@ -57,11 +57,11 @@ foreach ($values as $value) { Using increment: Initial value:string(0) "" -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d Result value:string(1) "1" Initial value:string(1) " " -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(1) @@ -70,28 +70,20 @@ Result value:float(16.5) Initial value:string(4) "1e10" Result value:float(10000000001) Initial value:string(4) "199A" - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "199B" Initial value:string(4) "A199" - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "A200" Initial value:string(4) "199Z" - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "200A" Initial value:string(4) "Z199" - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d Result value:string(4) "Z200" Initial value:string(11) "Hello world" -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d Result value:string(11) "Hello worle" Initial value:string(4) "🐘" -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d Result value:string(4) "🐘" Using decrement: Initial value:string(0) "" diff --git a/Zend/tests/in-de-crement/incdec_strings_exception.phpt b/Zend/tests/in-de-crement/incdec_strings_exception.phpt index af2bb72c0c736..4214a6a45878a 100644 --- a/Zend/tests/in-de-crement/incdec_strings_exception.phpt +++ b/Zend/tests/in-de-crement/incdec_strings_exception.phpt @@ -41,35 +41,31 @@ foreach ($values as $value) { } ?> --EXPECT-- -Deprecated: Increment on non-numeric string is deprecated +Deprecated: Increment on non-alphanumeric string is deprecated string(0) "" Deprecated: Decrement on empty string is deprecated as non-numeric string(0) "" -Deprecated: Increment on non-numeric string is deprecated +Deprecated: Increment on non-alphanumeric string is deprecated string(1) " " Deprecated: Decrement on non-numeric string has no effect and is deprecated string(1) " " -Deprecated: Increment on non-numeric string is deprecated -string(4) "199A" +string(4) "199B" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "199A" -Deprecated: Increment on non-numeric string is deprecated -string(4) "A199" +string(4) "199B" +string(4) "A200" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "A199" -Deprecated: Increment on non-numeric string is deprecated -string(4) "199Z" +string(4) "A200" +string(4) "200A" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "199Z" -Deprecated: Increment on non-numeric string is deprecated -string(4) "Z199" +string(4) "200A" +string(4) "Z200" Deprecated: Decrement on non-numeric string has no effect and is deprecated -string(4) "Z199" -Deprecated: Increment on non-numeric string is deprecated +string(4) "Z200" +Deprecated: Increment on non-alphanumeric string is deprecated string(11) "Hello world" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(11) "Hello world" -Deprecated: Increment on non-numeric string is deprecated +Deprecated: Increment on non-alphanumeric string is deprecated string(4) "🐘" Deprecated: Decrement on non-numeric string has no effect and is deprecated string(4) "🐘" diff --git a/Zend/tests/in-de-crement/incdec_types.phpt b/Zend/tests/in-de-crement/incdec_types.phpt index cee3277565a39..dfd850965146a 100644 --- a/Zend/tests/in-de-crement/incdec_types.phpt +++ b/Zend/tests/in-de-crement/incdec_types.phpt @@ -63,11 +63,11 @@ Initial value:float(0) Result value:float(1) Initial value:string(0) "" -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d Result value:string(1) "1" Initial value:string(1) " " -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d Result value:string(1) " " Initial value:string(1) "0" Result value:int(1) diff --git a/Zend/tests/in-de-crement/string_increment_various.phpt b/Zend/tests/in-de-crement/string_increment_various.phpt new file mode 100644 index 0000000000000..8499d823042b6 --- /dev/null +++ b/Zend/tests/in-de-crement/string_increment_various.phpt @@ -0,0 +1,107 @@ +--TEST-- +String increment on a variety of strings +--FILE-- + +--EXPECTF-- +string(2) "Ba" +string(2) "bA" +string(2) "B0" +string(2) "b0" +string(3) "AAa" +string(3) "aaA" +string(3) "10a" +string(3) "10A" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(1) "1" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(3) "-cd" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(2) "Z " + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(2) " A" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(2) "é" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(15) "あいうえお" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(2) "α" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(2) "ω" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(2) "Α" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(2) "Ω" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(8) "foo1.txu" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(4) "1f.6" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(9) "foo.1.txu" + +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d +string(5) "1.f.6" +string(3) "5e0" +float(6) diff --git a/Zend/tests/operator_unsupported_types.phpt b/Zend/tests/operator_unsupported_types.phpt index 3a3b8c0e3bdf3..ef169bb39fc29 100644 --- a/Zend/tests/operator_unsupported_types.phpt +++ b/Zend/tests/operator_unsupported_types.phpt @@ -2104,7 +2104,6 @@ Cannot increment stdClass Cannot decrement stdClass Cannot increment resource Cannot decrement resource -Warning: Increment on non-numeric string is deprecated No error for fop++ Warning: Decrement on non-numeric string has no effect and is deprecated No error for foo-- diff --git a/Zend/tests/temporary_cleaning_013.phpt b/Zend/tests/temporary_cleaning_013.phpt index 3a6acf9c99df9..e5f4b73bb14a2 100644 --- a/Zend/tests/temporary_cleaning_013.phpt +++ b/Zend/tests/temporary_cleaning_013.phpt @@ -320,7 +320,5 @@ caught Exception 27 caught Exception 28 caught Exception 29 caught Exception 30 - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d caught Exception 31 caught Exception 32 diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 1e1b94ad1c79b..a5517f6faf89a 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2502,17 +2502,32 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ int last=0; /* Shut up the compiler warning */ int ch; - zend_error(E_DEPRECATED, "Increment on non-numeric string is deprecated"); - if (EG(exception)) { - return; - } - if (Z_STRLEN_P(str) == 0) { + zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); + if (EG(exception)) { + return; + } zval_ptr_dtor_str(str); ZVAL_CHAR(str, '1'); return; } + { + const char *p = Z_STRVAL_P(str); + const char *e = Z_STRVAL_P(str) + Z_STRLEN_P(str); + while (p < e) { + char c = *p++; + if (UNEXPECTED( c < '0' || c > 'z' || (c < 'a' && c > 'Z') || (c < 'A' && c > '9') ) ) { + zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); + if (EG(exception)) { + return; + } + break; + } + } + } + + if (!Z_REFCOUNTED_P(str)) { Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0); Z_TYPE_INFO_P(str) = IS_STRING_EX; diff --git a/ext/ffi/tests/025.phpt b/ext/ffi/tests/025.phpt index 2e381658dd32d..ba1e75e223f0d 100644 --- a/ext/ffi/tests/025.phpt +++ b/ext/ffi/tests/025.phpt @@ -37,8 +37,6 @@ object(FFI\CData:char)#%d (1) { ["cdata"]=> string(1) "a" } - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d object(FFI\CData:char)#%d (1) { ["cdata"]=> string(1) "b" diff --git a/ext/opcache/tests/bug77058.phpt b/ext/opcache/tests/bug77058.phpt index e241281bd2daf..c8135c4a510d8 100644 --- a/ext/opcache/tests/bug77058.phpt +++ b/ext/opcache/tests/bug77058.phpt @@ -19,4 +19,6 @@ myfunc(); ?> --EXPECTF-- Warning: Undefined variable $x in %s on line %d + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d '2' is expected to be 2 diff --git a/ext/opcache/tests/jit/inc_022.phpt b/ext/opcache/tests/jit/inc_022.phpt index adddc189d0211..75971cff6c2e9 100644 --- a/ext/opcache/tests/jit/inc_022.phpt +++ b/ext/opcache/tests/jit/inc_022.phpt @@ -23,8 +23,7 @@ var_dump(inc(1.1)); var_dump(dec("5")); var_dump(dec(1.1)); ?> ---EXPECTF-- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +--EXPECT-- string(3) "abd" int(6) float(2.1) diff --git a/ext/opcache/tests/jit/inc_023.phpt b/ext/opcache/tests/jit/inc_023.phpt index 292c7a921d1a5..e9af990b63673 100644 --- a/ext/opcache/tests/jit/inc_023.phpt +++ b/ext/opcache/tests/jit/inc_023.phpt @@ -20,11 +20,7 @@ var_dump(++$test->prop); var_dump(--$test->prop); ?> --EXPECTF-- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d - Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(1) "c" Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d diff --git a/ext/opcache/tests/jit/inc_024.phpt b/ext/opcache/tests/jit/inc_024.phpt index 10d87febe5fef..e8a7f999f1ac4 100644 --- a/ext/opcache/tests/jit/inc_024.phpt +++ b/ext/opcache/tests/jit/inc_024.phpt @@ -24,52 +24,52 @@ function test($b) { test("0"); ?> --EXPECTF-- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d Deprecated: Decrement on non-numeric string has no effect and is deprecated in %s on line %d -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(5) "-INF0" string(260) "0-2-12-112-1112-11112-111112-1111112-11111112-111111112-1111111112-11111111112-111111111112-1111111111112-11111111111112-111111111111112-1111111111111112-11111111111111112-111111111111111112-1111111111111111112-1.1111111111111E+20-1.1111111111111E+191-ING-INF1" diff --git a/ext/opcache/tests/opt/inference_016.phpt b/ext/opcache/tests/opt/inference_016.phpt index 6ce2488bcd395..3958131255d4c 100644 --- a/ext/opcache/tests/opt/inference_016.phpt +++ b/ext/opcache/tests/opt/inference_016.phpt @@ -19,5 +19,6 @@ try { } ?> --EXPECT-- +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in Unknown on line 0 NULL Modulo by zero diff --git a/ext/opcache/tests/opt/inference_019.phpt b/ext/opcache/tests/opt/inference_019.phpt index f7b951a38f814..d590e8b0b5d28 100644 --- a/ext/opcache/tests/opt/inference_019.phpt +++ b/ext/opcache/tests/opt/inference_019.phpt @@ -18,5 +18,8 @@ function test() { test(); ?> DONE ---EXPECT-- +--EXPECTF-- +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in Unknown on line 0 + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d DONE diff --git a/ext/opcache/tests/opt/sccp_038.phpt b/ext/opcache/tests/opt/sccp_038.phpt index 810dc4c8b4ed5..30fe7e27a2507 100644 --- a/ext/opcache/tests/opt/sccp_038.phpt +++ b/ext/opcache/tests/opt/sccp_038.phpt @@ -15,5 +15,5 @@ foo(); ?> DONE --EXPECT-- -Deprecated: Increment on non-numeric string is deprecated in Unknown on line 0 +Deprecated: Increment on non-alphanumeric string is deprecated in Unknown on line 0 DONE diff --git a/tests/lang/operators/postinc_variationStr.phpt b/tests/lang/operators/postinc_variationStr.phpt index 3de057dfae4a6..a064b49835333 100644 --- a/tests/lang/operators/postinc_variationStr.phpt +++ b/tests/lang/operators/postinc_variationStr.phpt @@ -28,36 +28,30 @@ float(2.2) --- testing: '-7.7' --- float(-6.7) --- testing: 'abc' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "abd" --- testing: '123abc' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(6) "123abd" --- testing: '123e5' --- float(12300001) --- testing: '123e5xyz' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(8) "123e5xza" --- testing: ' 123abc' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(7) " 123abd" --- testing: '123 abc' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(7) "123 abd" --- testing: '123abc ' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(7) "123abc " --- testing: '3.4a' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(4) "3.4b" --- testing: 'a5.9' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(4) "a5.0" diff --git a/tests/lang/operators/preinc_variationStr.phpt b/tests/lang/operators/preinc_variationStr.phpt index 9378aba78d4f3..bcae316d8f9b7 100644 --- a/tests/lang/operators/preinc_variationStr.phpt +++ b/tests/lang/operators/preinc_variationStr.phpt @@ -28,72 +28,48 @@ float(2.2) --- testing: '-7.7' --- float(-6.7) --- testing: 'abc' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "abd" --- testing: '123abc' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(6) "123abd" --- testing: '123e5' --- float(12300001) --- testing: '123e5xyz' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(8) "123e5xza" --- testing: ' 123abc' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(7) " 123abd" --- testing: '123 abc' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(7) "123 abd" --- testing: '123abc ' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(7) "123abc " --- testing: '3.4a' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(4) "3.4b" --- testing: 'a5.9' --- -Deprecated: Increment on non-numeric string is deprecated in %s on line %d +Deprecated: Increment on non-alphanumeric string is deprecated in %s on line %d string(4) "a5.0" --- testing: 'z' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "aa" --- testing: 'az' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "ba" --- testing: 'zz' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "aaa" --- testing: 'Z' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "AA" --- testing: 'AZ' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(2) "BA" --- testing: 'ZZ' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "AAA" --- testing: '9z' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "10a" --- testing: '19z' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(3) "20a" --- testing: '99z' --- - -Deprecated: Increment on non-numeric string is deprecated in %s on line %d string(4) "100a" From 22a3fdb6ae9dc6c3090919b61e96c71f0e347e39 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 20 Jan 2023 14:27:13 +0000 Subject: [PATCH 10/23] Add str_increment() function --- Zend/zend_operators.c | 29 +++++----- Zend/zend_operators.h | 2 + ext/standard/basic_functions.stub.php | 2 + ext/standard/basic_functions_arginfo.h | 6 ++- ext/standard/string.c | 54 +++++++++++++++++++ .../tests/strings/str_increment_basic.phpt | 54 +++++++++++++++++++ .../tests/strings/str_increment_errors.phpt | 53 ++++++++++++++++++ 7 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 ext/standard/tests/strings/str_increment_basic.phpt create mode 100644 ext/standard/tests/strings/str_increment_errors.phpt diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index a5517f6faf89a..af865885a54dd 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2493,6 +2493,19 @@ ZEND_API bool ZEND_FASTCALL instanceof_function_slow(const zend_class_entry *ins #define UPPER_CASE 2 #define NUMERIC 3 +ZEND_API bool zend_string_only_has_ascii_alphanumeric(const zend_string *str) +{ + const char *p = ZSTR_VAL(str); + const char *e = ZSTR_VAL(str) + ZSTR_LEN(str); + while (p < e) { + char c = *p++; + if (UNEXPECTED( c < '0' || c > 'z' || (c < 'a' && c > 'Z') || (c < 'A' && c > '9') ) ) { + return false; + } + } + return true; +} + static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ { int carry=0; @@ -2512,18 +2525,10 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ return; } - { - const char *p = Z_STRVAL_P(str); - const char *e = Z_STRVAL_P(str) + Z_STRLEN_P(str); - while (p < e) { - char c = *p++; - if (UNEXPECTED( c < '0' || c > 'z' || (c < 'a' && c > 'Z') || (c < 'A' && c > '9') ) ) { - zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); - if (EG(exception)) { - return; - } - break; - } + if (UNEXPECTED(!zend_string_only_has_ascii_alphanumeric(Z_STR_P(str)))) { + zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); + if (EG(exception)) { + return; } } diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 67ac5fc45494d..4b47debc8032d 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -72,6 +72,8 @@ static zend_always_inline bool instanceof_function( return instance_ce == ce || instanceof_function_slow(instance_ce, ce); } +ZEND_API bool zend_string_only_has_ascii_alphanumeric(const zend_string *str); + /** * Checks whether the string "str" with length "length" is numeric. The value * of allow_errors determines whether it's required to be entirely numeric, or diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index f1603d66c4b78..8c9fa8f0f2962 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2348,6 +2348,8 @@ function strtoupper(string $string): string {} /** @compile-time-eval */ function strtolower(string $string): string {} +function str_increment(string $string): string {} + /** @refcount 1 */ function basename(string $path, string $suffix = ""): string {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index c4eba7d921d94..8cfebe50e96f3 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a15bbbd1d29dfd674dd2174b3be5678a0832116a */ + * Stub hash: a17ccc4d2ac0c1004e6c53f54792e9549c75789a */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -872,6 +872,8 @@ ZEND_END_ARG_INFO() #define arginfo_strtolower arginfo_base64_encode +#define arginfo_str_increment arginfo_base64_encode + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_basename, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, suffix, IS_STRING, 0, "\"\"") @@ -2447,6 +2449,7 @@ ZEND_FUNCTION(implode); ZEND_FUNCTION(strtok); ZEND_FUNCTION(strtoupper); ZEND_FUNCTION(strtolower); +ZEND_FUNCTION(str_increment); ZEND_FUNCTION(basename); ZEND_FUNCTION(dirname); ZEND_FUNCTION(pathinfo); @@ -3081,6 +3084,7 @@ static const zend_function_entry ext_functions[] = { ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strtok, arginfo_strtok) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strtoupper, arginfo_strtoupper) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strtolower, arginfo_strtolower) + ZEND_FE(str_increment, arginfo_str_increment) ZEND_FE(basename, arginfo_basename) ZEND_FE(dirname, arginfo_dirname) ZEND_FE(pathinfo, arginfo_pathinfo) diff --git a/ext/standard/string.c b/ext/standard/string.c index 335e6fd897128..90a15e08afac5 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1192,6 +1192,60 @@ PHP_FUNCTION(strtolower) } /* }}} */ +PHP_FUNCTION(str_increment) +{ + zend_string *str; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(str) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(str) == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); + } + if (!zend_string_only_has_ascii_alphanumeric(str)) { + zend_argument_value_error(1, "must be composed only of alphanumeric ASCII characters"); + RETURN_THROWS(); + } + + zend_string *incremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistant */ false); + size_t position = ZSTR_LEN(str)-1; + bool carry = false; + + do { + char c = ZSTR_VAL(incremented)[position]; + if (EXPECTED( (c >= 'a' && c < 'z') || (c >= 'A' && c < 'Z') || (c >= '0' && c < '9') )) { + carry = false; + ZSTR_VAL(incremented)[position]++; + } else { /* if 'z', 'Z', or '9' */ + carry = true; + if (c == '9') { + ZSTR_VAL(incremented)[position] = '0'; + } else { + ZSTR_VAL(incremented)[position] -= 25; + } + } + } while (carry && position-- > 0); + + if (UNEXPECTED(carry)) { + zend_string *tmp = zend_string_alloc(ZSTR_LEN(incremented)+1, 0); + memcpy(ZSTR_VAL(tmp) + 1, ZSTR_VAL(incremented), ZSTR_LEN(incremented)); + ZSTR_VAL(tmp)[ZSTR_LEN(incremented)+1] = '\0'; + switch (ZSTR_VAL(incremented)[0]) { + case '0': + ZSTR_VAL(tmp)[0] = '1'; + break; + default: + ZSTR_VAL(tmp)[0] = ZSTR_VAL(incremented)[0]; + break; + } + zend_string_release_ex(incremented, /* persistant */ false); + RETURN_STR(tmp); + } + RETURN_STR(incremented); +} + #if defined(PHP_WIN32) static bool _is_basename_start(const char *start, const char *pos) { diff --git a/ext/standard/tests/strings/str_increment_basic.phpt b/ext/standard/tests/strings/str_increment_basic.phpt new file mode 100644 index 0000000000000..1f238f6f0dbe5 --- /dev/null +++ b/ext/standard/tests/strings/str_increment_basic.phpt @@ -0,0 +1,54 @@ +--TEST-- +str_increment(): Incrementing various strings +--FILE-- + +--EXPECT-- +string(2) "Ba" +string(2) "Az" +string(2) "bA" +string(2) "aZ" +string(2) "B0" +string(2) "A9" +string(2) "b0" +string(2) "a9" +string(3) "AAa" +string(2) "Zz" +string(3) "aaA" +string(2) "zZ" +string(3) "10a" +string(2) "9z" +string(3) "10A" +string(2) "9Z" +string(3) "5e7" +string(3) "5e6" +string(1) "e" +string(1) "d" +string(1) "E" +string(1) "D" +string(1) "5" +string(1) "4" diff --git a/ext/standard/tests/strings/str_increment_errors.phpt b/ext/standard/tests/strings/str_increment_errors.phpt new file mode 100644 index 0000000000000..41e4ac10e1078 --- /dev/null +++ b/ext/standard/tests/strings/str_increment_errors.phpt @@ -0,0 +1,53 @@ +--TEST-- +str_increment(): Invalid strings to increment should throw a ValueError +--FILE-- +getMessage(), PHP_EOL; + } +} + +?> +--EXPECT-- +str_increment(): Argument #1 ($string) cannot be empty +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_increment(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters From eeb66723281dcbe26020e4070b142d9129858ee3 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 20 Jan 2023 14:43:20 +0000 Subject: [PATCH 11/23] Add str_decrement() function --- ext/standard/basic_functions.stub.php | 2 + ext/standard/basic_functions_arginfo.h | 6 ++- ext/standard/string.c | 45 ++++++++++++++++ .../tests/strings/str_decrement_basic.phpt | 54 +++++++++++++++++++ .../tests/strings/str_decrement_errors.phpt | 53 ++++++++++++++++++ .../strings/str_decrement_underflow.phpt | 38 +++++++++++++ 6 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/strings/str_decrement_basic.phpt create mode 100644 ext/standard/tests/strings/str_decrement_errors.phpt create mode 100644 ext/standard/tests/strings/str_decrement_underflow.phpt diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 8c9fa8f0f2962..0f2381c321b9f 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -2350,6 +2350,8 @@ function strtolower(string $string): string {} function str_increment(string $string): string {} +function str_decrement(string $string): string {} + /** @refcount 1 */ function basename(string $path, string $suffix = ""): string {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 8cfebe50e96f3..89f746aa5718c 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a17ccc4d2ac0c1004e6c53f54792e9549c75789a */ + * Stub hash: e01f6a979e72b1c3baf4602421cc966edfe50312 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0) @@ -874,6 +874,8 @@ ZEND_END_ARG_INFO() #define arginfo_str_increment arginfo_base64_encode +#define arginfo_str_decrement arginfo_base64_encode + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_basename, 0, 1, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, suffix, IS_STRING, 0, "\"\"") @@ -2450,6 +2452,7 @@ ZEND_FUNCTION(strtok); ZEND_FUNCTION(strtoupper); ZEND_FUNCTION(strtolower); ZEND_FUNCTION(str_increment); +ZEND_FUNCTION(str_decrement); ZEND_FUNCTION(basename); ZEND_FUNCTION(dirname); ZEND_FUNCTION(pathinfo); @@ -3085,6 +3088,7 @@ static const zend_function_entry ext_functions[] = { ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strtoupper, arginfo_strtoupper) ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strtolower, arginfo_strtolower) ZEND_FE(str_increment, arginfo_str_increment) + ZEND_FE(str_decrement, arginfo_str_decrement) ZEND_FE(basename, arginfo_basename) ZEND_FE(dirname, arginfo_dirname) ZEND_FE(pathinfo, arginfo_pathinfo) diff --git a/ext/standard/string.c b/ext/standard/string.c index 90a15e08afac5..04584433bb3bd 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1246,6 +1246,51 @@ PHP_FUNCTION(str_increment) RETURN_STR(incremented); } + +PHP_FUNCTION(str_decrement) +{ + zend_string *str; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_STR(str) + ZEND_PARSE_PARAMETERS_END(); + + if (ZSTR_LEN(str) == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); + } + if (!zend_string_only_has_ascii_alphanumeric(str)) { + zend_argument_value_error(1, "must be composed only of alphanumeric ASCII characters"); + RETURN_THROWS(); + } + + zend_string *decremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistant */ false); + size_t position = ZSTR_LEN(str)-1; + bool carry = false; + + do { + char c = ZSTR_VAL(decremented)[position]; + if (EXPECTED( (c > 'a' && c <= 'z') || (c > 'A' && c <= 'Z') || (c > '0' && c <= '9') )) { + carry = false; + ZSTR_VAL(decremented)[position]--; + } else { /* if 'a', 'A', or '0' */ + carry = true; + if (c == '0') { + ZSTR_VAL(decremented)[position] = '9'; + } else { + ZSTR_VAL(decremented)[position] += 25; + } + } + } while (carry && position-- > 0); + + if (UNEXPECTED(carry)) { + zend_string_release_ex(decremented, /* persistant */ false); + zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str)); + RETURN_THROWS(); + } + RETURN_STR(decremented); +} + #if defined(PHP_WIN32) static bool _is_basename_start(const char *start, const char *pos) { diff --git a/ext/standard/tests/strings/str_decrement_basic.phpt b/ext/standard/tests/strings/str_decrement_basic.phpt new file mode 100644 index 0000000000000..243cf1810c376 --- /dev/null +++ b/ext/standard/tests/strings/str_decrement_basic.phpt @@ -0,0 +1,54 @@ +--TEST-- +str_decrement(): Decrementing various strings +--FILE-- + +--EXPECT-- +string(2) "Ay" +string(2) "Az" +string(2) "aY" +string(2) "aZ" +string(2) "A8" +string(2) "A9" +string(2) "a8" +string(2) "a9" +string(2) "Yz" +string(2) "Za" +string(2) "yZ" +string(2) "zA" +string(2) "Y9" +string(2) "Z0" +string(2) "y9" +string(2) "z0" +string(3) "5e5" +string(3) "5e6" +string(1) "c" +string(1) "d" +string(1) "C" +string(1) "D" +string(1) "3" +string(1) "4" diff --git a/ext/standard/tests/strings/str_decrement_errors.phpt b/ext/standard/tests/strings/str_decrement_errors.phpt new file mode 100644 index 0000000000000..6f7f61e6b7b9a --- /dev/null +++ b/ext/standard/tests/strings/str_decrement_errors.phpt @@ -0,0 +1,53 @@ +--TEST-- +str_decrement(): Invalid strings to decrement should throw a ValueError +--FILE-- +getMessage(), PHP_EOL; + } +} + +?> +--EXPECT-- +str_decrement(): Argument #1 ($string) cannot be empty +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters +str_decrement(): Argument #1 ($string) must be composed only of alphanumeric ASCII characters diff --git a/ext/standard/tests/strings/str_decrement_underflow.phpt b/ext/standard/tests/strings/str_decrement_underflow.phpt new file mode 100644 index 0000000000000..a2c5520b9c50c --- /dev/null +++ b/ext/standard/tests/strings/str_decrement_underflow.phpt @@ -0,0 +1,38 @@ +--TEST-- +str_decrement(): Out of Range ValueErrors for strings that cannot be decremented +--FILE-- +getMessage(), PHP_EOL; + } +} + +?> +--EXPECT-- +str_decrement(): Argument #1 ($string) "0" is out of decrement range +str_decrement(): Argument #1 ($string) "a" is out of decrement range +str_decrement(): Argument #1 ($string) "A" is out of decrement range +str_decrement(): Argument #1 ($string) "00" is out of decrement range +str_decrement(): Argument #1 ($string) "Aa" is out of decrement range +str_decrement(): Argument #1 ($string) "aA" is out of decrement range +str_decrement(): Argument #1 ($string) "A0" is out of decrement range +str_decrement(): Argument #1 ($string) "a0" is out of decrement range +str_decrement(): Argument #1 ($string) "0a" is out of decrement range +str_decrement(): Argument #1 ($string) "0A" is out of decrement range From 3683dfa953fc08a27ee44578e8f2329e34ab96bc Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 20 Jan 2023 17:19:05 +0000 Subject: [PATCH 12/23] Add test to check polyfill behaves as str_increment() --- .../tests/strings/str_increment_polyfill.phpt | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 ext/standard/tests/strings/str_increment_polyfill.phpt diff --git a/ext/standard/tests/strings/str_increment_polyfill.phpt b/ext/standard/tests/strings/str_increment_polyfill.phpt new file mode 100644 index 0000000000000..36ad262598f4e --- /dev/null +++ b/ext/standard/tests/strings/str_increment_polyfill.phpt @@ -0,0 +1,59 @@ +--TEST-- +Verifying that the str_increment() polyfill behaves the same +--FILE-- + 'e', + 'F' => 'E', + 'g' => 'f', + 'G' => 'F', + }; + return $s; + } + } + return ++$s; +} + +$strictlyAlphaNumeric = [ + "Az", + "aZ", + "A9", + "a9", + // Carrying values until the beginning of the string + "Zz", + "zZ", + "9z", + "9Z", + // string interpretable as a number in scientific notation + "5e6", + "5E6", + "5e9", + "5E9", + // Interned strings + "d", + "D", + "4", +]; + +foreach ($strictlyAlphaNumeric as $s) { + if (str_increment($s) !== polyfill($s)) { + var_dump("Error:", str_increment($s), polyfill($s)); + } +} + +echo "DONE"; + +?> +--EXPECT-- +DONE From d2889bfcfc5f7a22199cf2adf3e1b3c19aad80cf Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 20 Jan 2023 17:19:37 +0000 Subject: [PATCH 13/23] Remove unused functions in zend_test for *NoOperation classes --- ext/zend_test/test.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 955be48c85490..a8bddaac14fa3 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -955,11 +955,6 @@ static zend_object *long_castable_no_operation_object_create(zend_class_entry *c return long_castable_no_operation_object_create_ex(ce, 0); } -static inline void long_castable_no_operation_create(zval *target, zend_long l) -{ - ZVAL_OBJ(target, long_castable_no_operation_object_create_ex(long_castable_no_operation_ce, l)); -} - static zend_result long_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) { if (type == IS_LONG) { @@ -996,11 +991,6 @@ static zend_object *float_castable_no_operation_object_create(zend_class_entry * return float_castable_no_operation_object_create_ex(ce, 0.0); } -static inline void float_castable_no_operation_create(zval *target, double d) -{ - ZVAL_OBJ(target, float_castable_no_operation_object_create_ex(float_castable_no_operation_ce, d)); -} - static zend_result float_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) { if (type == IS_DOUBLE) { @@ -1039,11 +1029,6 @@ static zend_object *numeric_castable_no_operation_object_create(zend_class_entry return numeric_castable_no_operation_object_create_ex(ce, &tmp); } -static inline void numeric_castable_no_operation_create(zval *target, const zval *n) -{ - ZVAL_OBJ(target, numeric_castable_no_operation_object_create_ex(numeric_castable_no_operation_ce, n)); -} - static zend_result numeric_castable_no_operation_cast_object(zend_object *obj, zval *result, int type) { if (type == _IS_NUMBER) { From 6541aaf1563c7573342c138d0f4d67fca77f612f Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 4 Jul 2023 21:40:25 +0100 Subject: [PATCH 14/23] Tweak zend_may_throw for -- with null values --- Zend/Optimizer/zend_inference.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index 7a322ea9e7c88..dd71215980f72 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -4681,9 +4681,11 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_DOUBLE|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); case ZEND_PRE_INC: case ZEND_POST_INC: + return (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); + /* null emits a warning as it has no effect compared to ++ which converts the value to 1 */ case ZEND_PRE_DEC: case ZEND_POST_DEC: - return (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); + return (t1 & (MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)); case ZEND_BOOL_NOT: case ZEND_JMPZ: case ZEND_JMPNZ: From 48bd88649c4708bcd06890870fb5ad9f95cc2298 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Thu, 13 Jul 2023 16:20:10 +0100 Subject: [PATCH 15/23] Address review --- Zend/zend_operators.c | 3 +-- ext/standard/string.c | 6 ++++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index af865885a54dd..77e05704b3a69 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2532,7 +2532,6 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ } } - if (!Z_REFCOUNTED_P(str)) { Z_STR_P(str) = zend_string_init(Z_STRVAL_P(str), Z_STRLEN_P(str), 0); Z_TYPE_INFO_P(str) = IS_STRING_EX; @@ -2666,7 +2665,7 @@ ZEND_API zend_result ZEND_FASTCALL increment_function(zval *op1) /* {{{ */ if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp, _IS_NUMBER) == SUCCESS) { ZEND_ASSERT(Z_TYPE(tmp) == IS_LONG || Z_TYPE(tmp) == IS_DOUBLE); zval_ptr_dtor(op1); - ZVAL_COPY(op1, &tmp); + ZVAL_COPY_VALUE(op1, &tmp); goto try_again; } ZEND_FALLTHROUGH; diff --git a/ext/standard/string.c b/ext/standard/string.c index 04584433bb3bd..4bb1659d21190 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1215,7 +1215,8 @@ PHP_FUNCTION(str_increment) do { char c = ZSTR_VAL(incremented)[position]; - if (EXPECTED( (c >= 'a' && c < 'z') || (c >= 'A' && c < 'Z') || (c >= '0' && c < '9') )) { + /* We know c is in ['a', 'z'], ['A', 'Z'], or ['0', '9'] range from zend_string_only_has_ascii_alphanumeric() */ + if (EXPECTED( c != 'z' && c != 'Z' && c != '9' )) { carry = false; ZSTR_VAL(incremented)[position]++; } else { /* if 'z', 'Z', or '9' */ @@ -1270,7 +1271,8 @@ PHP_FUNCTION(str_decrement) do { char c = ZSTR_VAL(decremented)[position]; - if (EXPECTED( (c > 'a' && c <= 'z') || (c > 'A' && c <= 'Z') || (c > '0' && c <= '9') )) { + /* We know c is in ['a', 'z'], ['A', 'Z'], or ['0', '9'] range from zend_string_only_has_ascii_alphanumeric() */ + if (EXPECTED( c != 'a' && c != 'A' && c != '0' )) { carry = false; ZSTR_VAL(decremented)[position]--; } else { /* if 'a', 'A', or '0' */ From 79921cbbd1f5ff038c131768da55e683df985442 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 14 Jul 2023 10:39:45 +0200 Subject: [PATCH 16/23] Fix memleak --- Zend/zend_operators.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 77e05704b3a69..e558a1d7d858b 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2752,7 +2752,7 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ if (Z_OBJ_HT_P(op1)->cast_object(Z_OBJ_P(op1), &tmp, _IS_NUMBER) == SUCCESS) { ZEND_ASSERT(Z_TYPE(tmp) == IS_LONG || Z_TYPE(tmp) == IS_DOUBLE); zval_ptr_dtor(op1); - ZVAL_COPY(op1, &tmp); + ZVAL_COPY_VALUE(op1, &tmp); goto try_again; } ZEND_FALLTHROUGH; From a689ba4d102bdac2d92099772c85f2cb7f181540 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 14 Jul 2023 10:40:54 +0200 Subject: [PATCH 17/23] Implement underflow handling for str_decrement --- ext/standard/string.c | 25 +++++++++++++------ .../tests/strings/str_decrement_basic.phpt | 25 +++++++++++++++++++ .../strings/str_decrement_underflow.phpt | 10 ++------ 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/ext/standard/string.c b/ext/standard/string.c index 4bb1659d21190..c6b89897ef888 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1209,7 +1209,7 @@ PHP_FUNCTION(str_increment) RETURN_THROWS(); } - zend_string *incremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistant */ false); + zend_string *incremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistent */ false); size_t position = ZSTR_LEN(str)-1; bool carry = false; @@ -1241,7 +1241,7 @@ PHP_FUNCTION(str_increment) ZSTR_VAL(tmp)[0] = ZSTR_VAL(incremented)[0]; break; } - zend_string_release_ex(incremented, /* persistant */ false); + zend_string_release_ex(incremented, /* persistent */ false); RETURN_STR(tmp); } RETURN_STR(incremented); @@ -1264,8 +1264,12 @@ PHP_FUNCTION(str_decrement) zend_argument_value_error(1, "must be composed only of alphanumeric ASCII characters"); RETURN_THROWS(); } + if (ZSTR_LEN(str) >= 1 && ZSTR_VAL(str)[0] == '0') { + zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str)); + RETURN_THROWS(); + } - zend_string *decremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistant */ false); + zend_string *decremented = zend_string_init(ZSTR_VAL(str), ZSTR_LEN(str), /* persistent */ false); size_t position = ZSTR_LEN(str)-1; bool carry = false; @@ -1285,10 +1289,17 @@ PHP_FUNCTION(str_decrement) } } while (carry && position-- > 0); - if (UNEXPECTED(carry)) { - zend_string_release_ex(decremented, /* persistant */ false); - zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str)); - RETURN_THROWS(); + if (UNEXPECTED(carry || ZSTR_VAL(decremented)[0] == '0')) { + if (ZSTR_LEN(decremented) == 1) { + zend_string_release_ex(decremented, /* persistent */ false); + zend_argument_value_error(1, "\"%s\" is out of decrement range", ZSTR_VAL(str)); + RETURN_THROWS(); + } + zend_string *tmp = zend_string_alloc(ZSTR_LEN(decremented) - 1, 0); + memcpy(ZSTR_VAL(tmp), ZSTR_VAL(decremented) + 1, ZSTR_LEN(decremented) - 1); + ZSTR_VAL(tmp)[ZSTR_LEN(decremented) - 1] = '\0'; + zend_string_release_ex(decremented, /* persistent */ false); + RETURN_STR(tmp); } RETURN_STR(decremented); } diff --git a/ext/standard/tests/strings/str_decrement_basic.phpt b/ext/standard/tests/strings/str_decrement_basic.phpt index 243cf1810c376..ca02290c16661 100644 --- a/ext/standard/tests/strings/str_decrement_basic.phpt +++ b/ext/standard/tests/strings/str_decrement_basic.phpt @@ -13,6 +13,15 @@ $strictlyAlphaNumeric = [ "zA", "Z0", "z0", + // Underflow, removing leading character + "Aa", + "aA", + "A0", + "a0", + "10", + "1A", + "1a", + "10a", // string interpretable as a number in scientific notation "5e6", // Interned strings @@ -44,6 +53,22 @@ string(2) "Y9" string(2) "Z0" string(2) "y9" string(2) "z0" +string(1) "z" +string(2) "Aa" +string(1) "Z" +string(2) "aA" +string(1) "9" +string(2) "A0" +string(1) "9" +string(2) "a0" +string(1) "9" +string(2) "10" +string(1) "Z" +string(2) "1A" +string(1) "z" +string(2) "1a" +string(2) "9z" +string(3) "10a" string(3) "5e5" string(3) "5e6" string(1) "c" diff --git a/ext/standard/tests/strings/str_decrement_underflow.phpt b/ext/standard/tests/strings/str_decrement_underflow.phpt index a2c5520b9c50c..ea60f0069342c 100644 --- a/ext/standard/tests/strings/str_decrement_underflow.phpt +++ b/ext/standard/tests/strings/str_decrement_underflow.phpt @@ -4,14 +4,11 @@ str_decrement(): Out of Range ValueErrors for strings that cannot be decremented --EXPECT-- +str_decrement(): Argument #1 ($string) cannot be empty str_decrement(): Argument #1 ($string) "0" is out of decrement range str_decrement(): Argument #1 ($string) "a" is out of decrement range str_decrement(): Argument #1 ($string) "A" is out of decrement range str_decrement(): Argument #1 ($string) "00" is out of decrement range -str_decrement(): Argument #1 ($string) "Aa" is out of decrement range -str_decrement(): Argument #1 ($string) "aA" is out of decrement range -str_decrement(): Argument #1 ($string) "A0" is out of decrement range -str_decrement(): Argument #1 ($string) "a0" is out of decrement range str_decrement(): Argument #1 ($string) "0a" is out of decrement range str_decrement(): Argument #1 ($string) "0A" is out of decrement range From de515bc53b05058a75150e042b2e2e8355cf490b Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 14 Jul 2023 18:11:07 +0100 Subject: [PATCH 18/23] Do not const evaluate ++/-- in SCCP Yes, now there are memory leaks and bugs but this is too much black magic for me --- Zend/Optimizer/sccp.c | 8 +++++++- ext/opcache/tests/jit/inc_017.phpt | 4 ++-- ext/opcache/tests/jit/inc_018.phpt | 4 ++-- ext/opcache/tests/opt/inference_016.phpt | 7 ++++--- ext/opcache/tests/opt/inference_019.phpt | 3 +-- ext/opcache/tests/opt/sccp_035.phpt | 4 ++-- ext/opcache/tests/opt/sccp_038.phpt | 4 ++-- 7 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index c35c60fd6be93..302070bd9c112 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -664,9 +664,15 @@ static inline zend_result ct_eval_assign_obj(zval *result, zval *value, const zv } static inline zend_result ct_eval_incdec(zval *result, uint8_t opcode, zval *op1) { + /* As of PHP 8.3 with the warning/deprecation notices any type other than int/double/null will emit a diagnostic if (Z_TYPE_P(op1) == IS_ARRAY || IS_PARTIAL_ARRAY(op1)) { return FAILURE; } + */ + /* Decrement on null emits a deprecation notice */ + if (Z_TYPE_P(op1) != IS_LONG && Z_TYPE_P(op1) != IS_DOUBLE /* && Z_TYPE_P(op1) != IS_NULL */) { + return FAILURE; + } ZVAL_COPY(result, op1); if (opcode == ZEND_PRE_INC @@ -2109,7 +2115,7 @@ static int try_remove_definition(sccp_ctx *ctx, int var_num, zend_ssa_var *var, break; default: break; - } + } } /* we cannot remove instruction that defines other variables */ return 0; diff --git a/ext/opcache/tests/jit/inc_017.phpt b/ext/opcache/tests/jit/inc_017.phpt index ab9b8cc3571fd..a78b6f013489b 100644 --- a/ext/opcache/tests/jit/inc_017.phpt +++ b/ext/opcache/tests/jit/inc_017.phpt @@ -17,6 +17,6 @@ function foo() { } var_dump(foo()); ?> ---EXPECT-- -Warning: Increment on type bool has no effect, this will change in the next major version of PHP in Unknown on line 0 +--EXPECTF-- +Warning: Increment on type bool has no effect, this will change in the next major version of PHP in %sinc_017.php on line 4 bool(true) diff --git a/ext/opcache/tests/jit/inc_018.phpt b/ext/opcache/tests/jit/inc_018.phpt index 9fc50904ef521..d160164699412 100644 --- a/ext/opcache/tests/jit/inc_018.phpt +++ b/ext/opcache/tests/jit/inc_018.phpt @@ -17,6 +17,6 @@ function foo() { } var_dump(foo()); ?> ---EXPECT-- -Warning: Increment on type bool has no effect, this will change in the next major version of PHP in Unknown on line 0 +--EXPECTF-- +Warning: Increment on type bool has no effect, this will change in the next major version of PHP in %sinc_018.php on line 4 bool(false) diff --git a/ext/opcache/tests/opt/inference_016.phpt b/ext/opcache/tests/opt/inference_016.phpt index 3958131255d4c..7d1733934fb6b 100644 --- a/ext/opcache/tests/opt/inference_016.phpt +++ b/ext/opcache/tests/opt/inference_016.phpt @@ -13,12 +13,13 @@ function test() { } } try { - @test(); + test(); } catch (Throwable $e) { echo $e->getMessage(), "\n"; } ?> ---EXPECT-- -Warning: Decrement on type null has no effect, this will change in the next major version of PHP in Unknown on line 0 +--EXPECTF-- NULL + +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %sinference_016.php on line %d Modulo by zero diff --git a/ext/opcache/tests/opt/inference_019.phpt b/ext/opcache/tests/opt/inference_019.phpt index d590e8b0b5d28..5e1f52688467b 100644 --- a/ext/opcache/tests/opt/inference_019.phpt +++ b/ext/opcache/tests/opt/inference_019.phpt @@ -19,7 +19,6 @@ test(); ?> DONE --EXPECTF-- -Warning: Decrement on type null has no effect, this will change in the next major version of PHP in Unknown on line 0 -Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %s on line %d +Warning: Decrement on type null has no effect, this will change in the next major version of PHP in %sinference_019.php on line %d DONE diff --git a/ext/opcache/tests/opt/sccp_035.phpt b/ext/opcache/tests/opt/sccp_035.phpt index 259df9ffb1495..3f86f2895e88a 100644 --- a/ext/opcache/tests/opt/sccp_035.phpt +++ b/ext/opcache/tests/opt/sccp_035.phpt @@ -13,6 +13,6 @@ function test() { } ?> DONE ---EXPECT-- -Deprecated: Decrement on empty string is deprecated as non-numeric in Unknown on line 0 +--EXPECTF-- +Deprecated: Decrement on empty string is deprecated as non-numeric in %ssccp_035.php on line 5 DONE diff --git a/ext/opcache/tests/opt/sccp_038.phpt b/ext/opcache/tests/opt/sccp_038.phpt index 30fe7e27a2507..165206056c6e5 100644 --- a/ext/opcache/tests/opt/sccp_038.phpt +++ b/ext/opcache/tests/opt/sccp_038.phpt @@ -14,6 +14,6 @@ function foo() { foo(); ?> DONE ---EXPECT-- -Deprecated: Increment on non-alphanumeric string is deprecated in Unknown on line 0 +--EXPECTF-- +Deprecated: Increment on non-alphanumeric string is deprecated in %ssccp_038.php on line 5 DONE From c0ceb4680eead4aa1bb16d5122a0e352ec277acc Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Fri, 14 Jul 2023 22:01:33 +0200 Subject: [PATCH 19/23] Fix memory leak --- Zend/Optimizer/sccp.c | 27 ++++++++++++++------------- ext/opcache/tests/opt/sccp_035.phpt | 3 +-- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 302070bd9c112..4ca36dab341b7 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -1381,21 +1381,22 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o && ctx->scdf.ssa->vars[ssa_op->op1_def].escape_state == ESCAPE_STATE_NO_ESCAPE) { zval tmp1, tmp2; - if (ct_eval_fetch_obj(&tmp1, op1, op2) == SUCCESS - && ct_eval_incdec(&tmp2, opline->opcode, &tmp1) == SUCCESS) { - - dup_partial_object(&zv, op1); - ct_eval_assign_obj(&zv, &tmp2, op2); - if (opline->opcode == ZEND_PRE_INC_OBJ || opline->opcode == ZEND_PRE_DEC_OBJ) { - SET_RESULT(result, &tmp2); - } else { - SET_RESULT(result, &tmp1); + if (ct_eval_fetch_obj(&tmp1, op1, op2) == SUCCESS) { + if (ct_eval_incdec(&tmp2, opline->opcode, &tmp1) == SUCCESS) { + dup_partial_object(&zv, op1); + ct_eval_assign_obj(&zv, &tmp2, op2); + if (opline->opcode == ZEND_PRE_INC_OBJ || opline->opcode == ZEND_PRE_DEC_OBJ) { + SET_RESULT(result, &tmp2); + } else { + SET_RESULT(result, &tmp1); + } + zval_ptr_dtor_nogc(&tmp1); + zval_ptr_dtor_nogc(&tmp2); + SET_RESULT(op1, &zv); + zval_ptr_dtor_nogc(&zv); + break; } zval_ptr_dtor_nogc(&tmp1); - zval_ptr_dtor_nogc(&tmp2); - SET_RESULT(op1, &zv); - zval_ptr_dtor_nogc(&zv); - break; } } } diff --git a/ext/opcache/tests/opt/sccp_035.phpt b/ext/opcache/tests/opt/sccp_035.phpt index 3f86f2895e88a..86965b13b5f3d 100644 --- a/ext/opcache/tests/opt/sccp_035.phpt +++ b/ext/opcache/tests/opt/sccp_035.phpt @@ -13,6 +13,5 @@ function test() { } ?> DONE ---EXPECTF-- -Deprecated: Decrement on empty string is deprecated as non-numeric in %ssccp_035.php on line 5 +--EXPECT-- DONE From 03a0f4e14f99ded24287b0808d8038dd491d4bc6 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sat, 15 Jul 2023 00:44:42 +0100 Subject: [PATCH 20/23] Allow SCCP for increment on null --- Zend/Optimizer/sccp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 4ca36dab341b7..d5486803e19a6 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -669,8 +669,7 @@ static inline zend_result ct_eval_incdec(zval *result, uint8_t opcode, zval *op1 return FAILURE; } */ - /* Decrement on null emits a deprecation notice */ - if (Z_TYPE_P(op1) != IS_LONG && Z_TYPE_P(op1) != IS_DOUBLE /* && Z_TYPE_P(op1) != IS_NULL */) { + if (Z_TYPE_P(op1) != IS_LONG && Z_TYPE_P(op1) != IS_DOUBLE && Z_TYPE_P(op1) != IS_NULL) { return FAILURE; } @@ -681,6 +680,11 @@ static inline zend_result ct_eval_incdec(zval *result, uint8_t opcode, zval *op1 || opcode == ZEND_POST_INC_OBJ) { increment_function(result); } else { + /* Decrement on null emits a deprecation notice */ + if (Z_TYPE_P(op1) == IS_NULL) { + zval_ptr_dtor(result); + return FAILURE; + } decrement_function(result); } return SUCCESS; From 9fd7212795707eb25ee8dc83c0b01199a75009f4 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sat, 15 Jul 2023 17:38:10 +0100 Subject: [PATCH 21/23] Error handler can change type of op Fix the empty string case, don't think this is the solution for non ASCII strings as I'm not sure *what* the behaviour should be --- .../decrement_diagnostic_change_type.phpt | 19 +++++++++ .../increment_diagnostic_change_type.phpt | 40 +++++++++++++++++++ ...nt_diagnostic_change_type_do_operator.phpt | 36 +++++++++++++++++ Zend/zend_operators.c | 21 ++++++---- 4 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 Zend/tests/in-de-crement/decrement_diagnostic_change_type.phpt create mode 100644 Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt create mode 100644 Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt diff --git a/Zend/tests/in-de-crement/decrement_diagnostic_change_type.phpt b/Zend/tests/in-de-crement/decrement_diagnostic_change_type.phpt new file mode 100644 index 0000000000000..aec9b5b3cdecb --- /dev/null +++ b/Zend/tests/in-de-crement/decrement_diagnostic_change_type.phpt @@ -0,0 +1,19 @@ +--TEST-- +Error handler can change type of operand of -- +--FILE-- + +DONE +--EXPECT-- +int(-1) +DONE diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt new file mode 100644 index 0000000000000..141332c70c165 --- /dev/null +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt @@ -0,0 +1,40 @@ +--TEST-- +Error handler can change type of operand of ++ +--FILE-- + +DONE +--EXPECT-- +string(1) "1" +string(50) "Increment on non-alphanumeric string is deprecated" +object(stdClass)#3 (0) { +} +string(50) "Increment on non-alphanumeric string is deprecated" +object(stdClass)#3 (0) { +} +DONE diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt new file mode 100644 index 0000000000000..b0963c5a62330 --- /dev/null +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt @@ -0,0 +1,36 @@ +--TEST-- +Error handler can change type of operand of ++ to object with do_operator +--EXTENSIONS-- +gmp +--FILE-- + +DONE +--EXPECT-- +string(50) "Increment on non-alphanumeric string is deprecated" +object(GMP)#2 (1) { + ["num"]=> + string(2) "10" +} +string(50) "Increment on non-alphanumeric string is deprecated" +object(GMP)#2 (1) { + ["num"]=> + string(2) "10" +} +DONE diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index e558a1d7d858b..5e78864e80031 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2506,7 +2506,7 @@ ZEND_API bool zend_string_only_has_ascii_alphanumeric(const zend_string *str) return true; } -static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ +static bool ZEND_FASTCALL increment_string(zval *str) /* {{{ */ { int carry=0; size_t pos=Z_STRLEN_P(str)-1; @@ -2515,20 +2515,25 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ int last=0; /* Shut up the compiler warning */ int ch; - if (Z_STRLEN_P(str) == 0) { + if (UNEXPECTED(Z_STRLEN_P(str) == 0)) { zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); if (EG(exception)) { - return; + return false; } - zval_ptr_dtor_str(str); + /* A userland error handler can change the type from string to something else */ + zval_ptr_dtor(str); ZVAL_CHAR(str, '1'); - return; + return true; } if (UNEXPECTED(!zend_string_only_has_ascii_alphanumeric(Z_STR_P(str)))) { zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); if (EG(exception)) { - return; + return false; + } + /* A userland error handler can change the type from string to something else */ + if (Z_TYPE_P(str) != IS_STRING) { + return false; } } @@ -2601,6 +2606,7 @@ static void ZEND_FASTCALL increment_string(zval *str) /* {{{ */ zend_string_free(Z_STR_P(str)); ZVAL_NEW_STR(str, t); } + return true; } /* }}} */ @@ -2699,7 +2705,8 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ if (EG(exception)) { return FAILURE; } - zval_ptr_dtor_str(op1); + /* A userland error handler can change the type from string to something else */ + zval_ptr_dtor(op1); ZVAL_LONG(op1, -1); break; } From afd16957d4195f03bebc4f125179ebd5343eb44e Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 16 Jul 2023 18:29:55 +0100 Subject: [PATCH 22/23] Fix behaviour of changing type of op if non-ascii --- .../increment_diagnostic_change_type.phpt | 6 ++---- ...increment_diagnostic_change_type_do_operator.phpt | 10 ++-------- Zend/zend_operators.c | 12 ++++++++---- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt index 141332c70c165..e124bfe907ebc 100644 --- a/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type.phpt @@ -32,9 +32,7 @@ DONE --EXPECT-- string(1) "1" string(50) "Increment on non-alphanumeric string is deprecated" -object(stdClass)#3 (0) { -} +string(4) "foo!" string(50) "Increment on non-alphanumeric string is deprecated" -object(stdClass)#3 (0) { -} +string(1) "!" DONE diff --git a/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt index b0963c5a62330..e20159a578cd9 100644 --- a/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt +++ b/Zend/tests/in-de-crement/increment_diagnostic_change_type_do_operator.phpt @@ -24,13 +24,7 @@ var_dump($x); DONE --EXPECT-- string(50) "Increment on non-alphanumeric string is deprecated" -object(GMP)#2 (1) { - ["num"]=> - string(2) "10" -} +string(4) "foo!" string(50) "Increment on non-alphanumeric string is deprecated" -object(GMP)#2 (1) { - ["num"]=> - string(2) "10" -} +string(1) "!" DONE diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 5e78864e80031..293d7cc029eac 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -2527,14 +2527,18 @@ static bool ZEND_FASTCALL increment_string(zval *str) /* {{{ */ } if (UNEXPECTED(!zend_string_only_has_ascii_alphanumeric(Z_STR_P(str)))) { + zend_string *zstr = Z_STR_P(str); + GC_TRY_ADDREF(zstr); zend_error(E_DEPRECATED, "Increment on non-alphanumeric string is deprecated"); if (EG(exception)) { + GC_TRY_DELREF(zstr); + if (!GC_REFCOUNT(zstr)) { + efree(zstr); + } return false; } - /* A userland error handler can change the type from string to something else */ - if (Z_TYPE_P(str) != IS_STRING) { - return false; - } + zval_ptr_dtor(str); + ZVAL_STR(str, zstr); } if (!Z_REFCOUNTED_P(str)) { From 12d84fe241fdcbb3d17601b1e3d86bfdcbace983 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 16 Jul 2023 18:42:56 +0100 Subject: [PATCH 23/23] UPGRADING --- UPGRADING | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/UPGRADING b/UPGRADING index 434fdc1fd56df..bd8696f2245ea 100644 --- a/UPGRADING +++ b/UPGRADING @@ -118,6 +118,14 @@ PHP 8.3 UPGRADE NOTES 4. Deprecated Functionality ======================================== +- Core + . Using the ++ operator on empty, non-numeric, or non-alphanumeric strings + is now deprecated. Moreover, incrementing non-numeric strings is soft + deprecated and the new str_increment() function should be used instead. + RFC: https://wiki.php.net/rfc/saner-inc-dec-operators + . Using the -- operator on empty or non-numeric strings is now deprecated. + RFC: https://wiki.php.net/rfc/saner-inc-dec-operators + - Intl . The U_MULTIPLE_DECIMAL_SEP*E*RATORS constant had been deprecated, using the U_MULTIPLE_DECIMAL_SEP*A*RATORS instead is recommended. @@ -300,6 +308,10 @@ PHP 8.3 UPGRADE NOTES - Sockets: . Added socket_atmark to checks if the socket is OOB marked. +- Standard: + . Added the str_increment() and str_decrement() functions. + RFC: https://wiki.php.net/rfc/saner-inc-dec-operators + - Zip: . Added ZipArchive::setArchiveFlag and ZipArchive::getArchiveFlag methods. @@ -321,6 +333,13 @@ PHP 8.3 UPGRADE NOTES not reachable except by iterating over the WeakMap (reachability via iteration is considered weak). Previously, such entries would never be automatically removed. (See GH-10932.) + . The ++ and -- operators now emit warnings when attempting to increment + values of type bool as this will change in the next major version. + A warning is emitted when trying to decrement values of type null, as + this will change in the next major version. + Internal objects that implement an _IS_NUMBER cast but not a do_operator + handler that overrides addition and substraction now can be incremented + and decrement as if one would do $o += 1 or $o -= 1 - DOM: . The DOM lifetime mechanism has been reworked such that implicitly removed