Skip to content

Commit f2b0996

Browse files
committed
Convert "cannot add element" warning to exception
1 parent 36eecc1 commit f2b0996

14 files changed

+129
-100
lines changed

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ PHP 8.0 UPGRADE NOTES
9191
the value into an object (if it was null, false or an empty string) or
9292
ignored the write altogether (in all other cases).
9393
RFC: Part of https://wiki.php.net/rfc/engine_warnings
94+
. Attempting to append an element to an array for which the PHP_INT_MAX key
95+
is already used will now result in an Error exception. Previously this was
96+
a warning.
97+
RFC: Part of https://wiki.php.net/rfc/engine_warnings
9498

9599
- COM:
96100
. Removed the ability to import case-insensitive constants from type

Zend/tests/array_literal_next_element_error.phpt

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,21 @@ Next free element may overflow in array literals
44
<?php
55

66
$i = PHP_INT_MAX;
7-
$array = [$i => 42, new stdClass];
8-
var_dump($array);
9-
10-
const FOO = [PHP_INT_MAX => 42, "foo"];
11-
var_dump(FOO);
12-
13-
?>
14-
--EXPECTF--
15-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
16-
array(1) {
17-
[%d]=>
18-
int(42)
7+
try {
8+
$array = [$i => 42, new stdClass];
9+
var_dump($array);
10+
} catch (Error $e) {
11+
echo $e->getMessage(), "\n";
1912
}
2013

21-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
22-
array(1) {
23-
[%d]=>
24-
int(42)
14+
function test($x = [PHP_INT_MAX => 42, "foo"]) {}
15+
try {
16+
test();
17+
} catch (Error $e) {
18+
echo $e->getMessage(), "\n";
2519
}
20+
21+
?>
22+
--EXPECT--
23+
Cannot add element to the array as the next element is already occupied
24+
Cannot add element to the array as the next element is already occupied

Zend/tests/array_unpack/already_occupied.phpt

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,28 @@ Appending to an array via unpack may fail
66
<?php
77

88
$arr = [1, 2, 3];
9-
var_dump([PHP_INT_MAX-1 => 0, ...$arr]);
10-
11-
var_dump([PHP_INT_MAX-1 => 0, ...[1, 2, 3]]);
12-
13-
const ARR = [1, 2, 3];
14-
const ARR2 = [PHP_INT_MAX-1 => 0, ...ARR];
15-
var_dump(ARR2);
16-
17-
?>
18-
--EXPECTF--
19-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
20-
array(2) {
21-
[9223372036854775806]=>
22-
int(0)
23-
[9223372036854775807]=>
24-
int(1)
9+
try {
10+
var_dump([PHP_INT_MAX-1 => 0, ...$arr]);
11+
} catch (Error $e) {
12+
echo $e->getMessage(), "\n";
2513
}
2614

27-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
28-
array(2) {
29-
[9223372036854775806]=>
30-
int(0)
31-
[9223372036854775807]=>
32-
int(1)
15+
try {
16+
var_dump([PHP_INT_MAX-1 => 0, ...[1, 2, 3]]);
17+
} catch (Error $e) {
18+
echo $e->getMessage(), "\n";
3319
}
3420

35-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
36-
array(2) {
37-
[9223372036854775806]=>
38-
int(0)
39-
[9223372036854775807]=>
40-
int(1)
21+
const ARR = [1, 2, 3];
22+
function test($x = [PHP_INT_MAX-1 => 0, ...ARR]) {}
23+
try {
24+
test();
25+
} catch (Error $e) {
26+
echo $e->getMessage(), "\n";
4127
}
28+
29+
?>
30+
--EXPECT--
31+
Cannot add element to the array as the next element is already occupied
32+
Cannot add element to the array as the next element is already occupied
33+
Cannot add element to the array as the next element is already occupied

Zend/tests/assign_dim_obj_null_return.phpt

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,22 @@ function test() {
77
$array = [PHP_INT_MAX => 42];
88
$true = true;
99

10-
var_dump($array[] = 123);
10+
try {
11+
var_dump($array[] = 123);
12+
} catch (Error $e) {
13+
echo $e->getMessage(), "\n";
14+
}
15+
1116
var_dump($array[[]] = 123);
1217
var_dump($array[new stdClass] = 123);
1318
var_dump($true[123] = 456);
1419

15-
var_dump($array[] += 123);
20+
try {
21+
var_dump($array[] += 123);
22+
} catch (Error $e) {
23+
echo $e->getMessage(), "\n";
24+
}
25+
1626
var_dump($array[[]] += 123);
1727
var_dump($array[new stdClass] += 123);
1828
var_dump($true[123] += 456);
@@ -33,8 +43,7 @@ test();
3343

3444
?>
3545
--EXPECTF--
36-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
37-
NULL
46+
Cannot add element to the array as the next element is already occupied
3847

3948
Warning: Illegal offset type in %s on line %d
4049
NULL
@@ -44,9 +53,7 @@ NULL
4453

4554
Warning: Cannot use a scalar value as an array in %s on line %d
4655
NULL
47-
48-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
49-
NULL
56+
Cannot add element to the array as the next element is already occupied
5057

5158
Warning: Illegal offset type in %s on line %d
5259
NULL

Zend/tests/assign_ref_error_var_handling.phpt

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,22 @@ function val() {
99

1010
$var = 24;
1111
$arr = [PHP_INT_MAX => "foo"];
12-
var_dump($arr[] =& $var);
12+
try {
13+
var_dump($arr[] =& $var);
14+
} catch (Error $e) {
15+
echo $e->getMessage(), "\n";
16+
}
1317
var_dump(count($arr));
14-
var_dump($arr[] =& val());
18+
try {
19+
var_dump($arr[] =& val());
20+
} catch (Error $e) {
21+
echo $e->getMessage(), "\n";
22+
}
1523
var_dump(count($arr));
1624

1725
?>
18-
--EXPECTF--
19-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
20-
NULL
26+
--EXPECT--
27+
Cannot add element to the array as the next element is already occupied
2128
int(1)
22-
23-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
24-
NULL
29+
Cannot add element to the array as the next element is already occupied
2530
int(1)

Zend/tests/bug36303.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
Bug #36303 (foreach on error_zval produces segfault)
33
--FILE--
44
<?php
5-
$x=[PHP_INT_MAX=>"test"];
6-
foreach ($x[] as &$v) {
5+
$x = [];
6+
foreach ($x[[]] as &$v) {
77
}
88
echo "ok\n";
99
?>
1010
--EXPECTF--
11-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
11+
Warning: Illegal offset type in %s on line %d
1212

1313
Warning: Invalid argument supplied for foreach() in %s on line %d
1414
ok

Zend/tests/bug47836.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@ Bug #47836 (array operator [] inconsistency when the array has PHP_INT_MAX index
44
<?php
55

66
$arr[PHP_INT_MAX] = 1;
7-
$arr[] = 2;
7+
try {
8+
$arr[] = 2;
9+
} catch (Error $e) {
10+
echo $e->getMessage(), "\n";
11+
}
812

913
var_dump($arr);
1014
?>
1115
--EXPECTF--
12-
Warning: Cannot add element to the array as the next element is already occupied in %s on line 4
16+
Cannot add element to the array as the next element is already occupied
1317
array(1) {
1418
[%d]=>
1519
int(1)

Zend/tests/bug52237.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
Bug #52237 (Crash when passing the reference of the property of a non-object)
33
--FILE--
44
<?php
5-
$data = [PHP_INT_MAX => 'test'];
6-
preg_match('//', '', $data[]);
5+
$data = [];
6+
preg_match('//', '', $data[[]]);
77
var_dump(count($data));
88
?>
99
--EXPECTF--
10-
Warning: Cannot add element to the array as the next element is already occupied in %s on line %d
11-
int(1)
10+
Warning: Illegal offset type in %s on line %d
11+
int(0)

Zend/tests/bug69017.phpt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ class c1
1616

1717
c1::$a1[] = 1;
1818
c1::$a2[] = 1;
19-
c1::$a3[] = 1;
19+
try {
20+
c1::$a3[] = 1;
21+
} catch (Error $e) {
22+
echo $e->getMessage(), "\n";
23+
}
2024

2125
var_dump(c1::$a1);
2226
var_dump(c1::$a2);
2327
var_dump(c1::$a3);
2428
?>
2529
--EXPECTF--
26-
Warning: Cannot add element to the array as the next element is already occupied in %sbug69017.php on line %d
30+
Cannot add element to the array as the next element is already occupied
2731
array(2) {
2832
[1]=>
2933
string(3) "one"

Zend/tests/bug71841.phpt

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,33 @@
11
--TEST--
22
Bug #71841 (EG(error_zval) is not handled well)
3-
--INI--
4-
error_reporting=0
53
--FILE--
64
<?php
75
$z = unserialize('O:1:"A":0:{}');
8-
var_dump($z->e.=0);
9-
var_dump(++$z->x);
10-
var_dump($z->y++);
6+
@var_dump($z->e.=0);
7+
@var_dump(++$z->x);
8+
@var_dump($z->y++);
119

1210
$y = array(PHP_INT_MAX => 0);
13-
var_dump($y[] .= 0);
14-
var_dump(++$y[]);
15-
var_dump($y[]++);
11+
try {
12+
var_dump($y[] .= 0);
13+
} catch (Error $e) {
14+
echo $e->getMessage(), "\n";
15+
}
16+
try {
17+
var_dump(++$y[]);
18+
} catch (Error $e) {
19+
echo $e->getMessage(), "\n";
20+
}
21+
try {
22+
var_dump($y[]++);
23+
} catch (Error $e) {
24+
echo $e->getMessage(), "\n";
25+
}
1626
?>
1727
--EXPECT--
1828
NULL
1929
NULL
2030
NULL
21-
NULL
22-
NULL
23-
NULL
31+
Cannot add element to the array as the next element is already occupied
32+
Cannot add element to the array as the next element is already occupied
33+
Cannot add element to the array as the next element is already occupied

Zend/zend_ast.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,9 @@ static int zend_ast_add_array_element(zval *result, zval *offset, zval *expr)
411411
switch (Z_TYPE_P(offset)) {
412412
case IS_UNDEF:
413413
if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), expr)) {
414-
zend_error(E_WARNING,
414+
zend_throw_error(NULL,
415415
"Cannot add element to the array as the next element is already occupied");
416-
zval_ptr_dtor_nogc(expr);
416+
return FAILURE;
417417
}
418418
break;
419419
case IS_STRING:
@@ -458,8 +458,9 @@ static int zend_ast_add_unpacked_element(zval *result, zval *expr) {
458458
return FAILURE;
459459
} else {
460460
if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), val)) {
461-
zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
462-
break;
461+
zend_throw_error(NULL,
462+
"Cannot add element to the array as the next element is already occupied");
463+
return FAILURE;
463464
}
464465
Z_TRY_ADDREF_P(val);
465466
}

Zend/zend_execute.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1892,7 +1892,7 @@ static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_scalar_as_array(v
18921892

18931893
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_cannot_add_element(void)
18941894
{
1895-
zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
1895+
zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
18961896
}
18971897

18981898
static zend_never_inline ZEND_COLD void ZEND_FASTCALL zend_use_resource_as_offset(const zval *dim)

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,20 +1975,20 @@ static int zend_jit_cannot_add_element_stub(dasm_State **Dst)
19751975
| SET_Z_TYPE_INFO FP + r0, IS_NULL
19761976
|1:
19771977
|.if X64WIN
1978-
| mov CARG1, E_WARNING
1978+
| xor CARG1, CARG1
19791979
| LOAD_ADDR CARG2, "Cannot add element to the array as the next element is already occupied"
1980-
| EXT_CALL zend_error, r0
1980+
| EXT_CALL zend_throw_error, r0
19811981
| add r4, 0x28
19821982
|.elif X64
1983-
| mov CARG1, E_WARNING
1983+
| xor CARG1, CARG1
19841984
| LOAD_ADDR CARG2, "Cannot add element to the array as the next element is already occupied"
1985-
| EXT_CALL zend_error, r0
1985+
| EXT_CALL zend_throw_error, r0
19861986
| add r4, 8
19871987
|.else
19881988
| sub r4, 8
19891989
| push "Cannot add element to the array as the next element is already occupied"
1990-
| push E_WARNING
1991-
| EXT_CALL zend_error, r0
1990+
| push 0
1991+
| EXT_CALL zend_throw_error, r0
19921992
| add r4, 28
19931993
|.endif
19941994
| ret
@@ -4644,7 +4644,7 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, zend_op_
46444644
| jz >1
46454645
|.cold_code
46464646
|1:
4647-
| // zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
4647+
| // zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
46484648
| CANNOT_ADD_ELEMENT opline
46494649
| //ZEND_VM_C_GOTO(assign_dim_op_ret_null);
46504650
| jmp >9
@@ -4880,7 +4880,7 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, zend_
48804880
| jz >1
48814881
|.cold_code
48824882
|1:
4883-
| // zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
4883+
| // zend_throw_error(NULL, "Cannot add element to the array as the next element is already occupied");
48844884
| CANNOT_ADD_ELEMENT opline
48854885
| //ZEND_VM_C_GOTO(assign_dim_op_ret_null);
48864886
| jmp >9

0 commit comments

Comments
 (0)