Skip to content

[RFC] Path to Saner Increment/Decrement operators #10358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
Jul 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
48a0764
Add more behavioural tests for incdec operators
Girgias Nov 21, 2022
c192808
Raise no effect warning if inc/dec operator is used on bool
Girgias Nov 21, 2022
ac1c208
Emit warnings and deprecations for inc/dec with strings
Girgias Nov 21, 2022
bac48a0
Handle exceptions in Opcodes
Girgias Jun 18, 2022
5e14fbb
Add tests for in/decrement with castable numeric objects not implemen…
Girgias Jan 13, 2023
11fcfd1
Update messages to reflect 0.2 RFC version
Girgias Jan 14, 2023
fd2b76f
Add support to ++/-- for objects castable to _IS_NUMBER
Girgias Jan 14, 2023
ba6956f
Amend tests
Girgias Jan 17, 2023
a7c12f6
Do not deprecate purely alphanumeric strings yet
Girgias Jan 19, 2023
22a3fdb
Add str_increment() function
Girgias Jan 20, 2023
eeb6672
Add str_decrement() function
Girgias Jan 20, 2023
3683dfa
Add test to check polyfill behaves as str_increment()
Girgias Jan 20, 2023
d2889bf
Remove unused functions in zend_test for *NoOperation classes
Girgias Jan 20, 2023
6541aaf
Tweak zend_may_throw for -- with null values
Girgias Jul 4, 2023
48bd886
Address review
Girgias Jul 13, 2023
79921cb
Fix memleak
iluuu1994 Jul 14, 2023
a689ba4
Implement underflow handling for str_decrement
iluuu1994 Jul 14, 2023
de515bc
Do not const evaluate ++/-- in SCCP
Girgias Jul 14, 2023
c0ceb46
Fix memory leak
arnaud-lb Jul 14, 2023
03a0f4e
Allow SCCP for increment on null
Girgias Jul 14, 2023
9fd7212
Error handler can change type of op
Girgias Jul 15, 2023
afd1695
Fix behaviour of changing type of op if non-ascii
Girgias Jul 16, 2023
12d84fe
UPGRADING
Girgias Jul 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.

Expand All @@ -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
Expand Down
39 changes: 25 additions & 14 deletions Zend/Optimizer/sccp.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,9 +664,14 @@ 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;
}
*/
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
Expand All @@ -675,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;
Expand Down Expand Up @@ -1375,21 +1385,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;
}
}
}
Expand Down Expand Up @@ -2109,7 +2120,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;
Expand Down
4 changes: 3 additions & 1 deletion Zend/Optimizer/zend_inference.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_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:
Expand Down
67 changes: 0 additions & 67 deletions Zend/tests/decrement_001.phpt

This file was deleted.

67 changes: 0 additions & 67 deletions Zend/tests/decrement_001_64bit.phpt

This file was deleted.

25 changes: 25 additions & 0 deletions Zend/tests/in-de-crement/decrement_001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
Decrementing min int values 32bit
--SKIPIF--
<?php if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only"); ?>
--INI--
precision=14
--FILE--
<?php

$values = [
-PHP_INT_MAX-1,
(string)(-PHP_INT_MAX-1),
];

foreach ($values as $var) {
$var--;
var_dump($var);
}

echo "Done\n";
?>
--EXPECT--
float(-2147483649)
float(-2147483649)
Done
25 changes: 25 additions & 0 deletions Zend/tests/in-de-crement/decrement_001_64bit.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
--TEST--
Decrementing min int values 64bit
--SKIPIF--
<?php if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platform only"); ?>
--INI--
precision=14
--FILE--
<?php

$values = [
-PHP_INT_MAX-1,
(string)(-PHP_INT_MAX-1),
];

foreach ($values as $var) {
$var--;
var_dump($var);
}

echo "Done\n";
?>
--EXPECT--
float(-9.223372036854776E+18)
float(-9.223372036854776E+18)
Done
19 changes: 19 additions & 0 deletions Zend/tests/in-de-crement/decrement_diagnostic_change_type.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
Error handler can change type of operand of --
--FILE--
<?php

set_error_handler(function () {
global $x;
$x = 1;
});

$x = '';
$x--;
var_dump($x);

?>
DONE
--EXPECT--
int(-1)
DONE
Loading