1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Zend: Warn when destructuring non-array values (#19439)

RFC: https://wiki.php.net/rfc/warnings-php-8-5#destructuring_non-array_values
This commit is contained in:
Gina Peter Banyard
2025-08-29 16:06:34 +01:00
committed by GitHub
parent fc467dcb64
commit 8747e9ae18
17 changed files with 226 additions and 81 deletions

View File

@@ -7,16 +7,48 @@ foreach (array(array(1,2), array(3,4)) as list($a, )) {
var_dump($a);
}
echo "Array of strings:\n";
$array = [['a', 'b'], 'c', 'd'];
foreach($array as list(, $a)) {
var_dump($a);
}
echo "Array of ints:\n";
$array = [[5, 6], 10, 20];
foreach($array as list(, $a)) {
var_dump($a);
}
echo "Array of nulls:\n";
$array = [[null, null], null, null];
foreach($array as list(, $a)) {
var_dump($a);
}
?>
--EXPECT--
--EXPECTF--
int(1)
int(3)
Array of strings:
string(1) "b"
Warning: Cannot use string as array in %s on line %d
NULL
Warning: Cannot use string as array in %s on line %d
NULL
Array of ints:
int(6)
Warning: Cannot use int as array in %s on line %d
NULL
Warning: Cannot use int as array in %s on line %d
NULL
Array of nulls:
NULL
NULL
NULL

View File

@@ -8,5 +8,9 @@ Bug #39304 (Segmentation fault with list unpacking of string offset)
?>
--EXPECTF--
Warning: Uninitialized string offset 0 in %s on line %d
Warning: Cannot use string as array in %s on line %d
Warning: Cannot use string as array in %s on line %d
NULL
NULL

View File

@@ -0,0 +1,18 @@
--TEST--
Destructuring with list() a value of type bool
--FILE--
<?php
$v = true;
list($a, $b) = $v;
var_dump($a, $b);
?>
--EXPECTF--
Warning: Cannot use bool as array in %s on line %d
Warning: Cannot use bool as array in %s on line %d
NULL
NULL

View File

@@ -0,0 +1,18 @@
--TEST--
Destructuring with list() a value of type float
--FILE--
<?php
$v = 25.64;
list($a, $b) = $v;
var_dump($a, $b);
?>
--EXPECTF--
Warning: Cannot use float as array in %s on line %d
Warning: Cannot use float as array in %s on line %d
NULL
NULL

View File

@@ -0,0 +1,18 @@
--TEST--
Destructuring with list() a value of type int
--FILE--
<?php
$v = 5;
list($a, $b) = $v;
var_dump($a, $b);
?>
--EXPECTF--
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
NULL
NULL

View File

@@ -0,0 +1,12 @@
--TEST--
Destructuring with list() a value of type null
--FILE--
<?php
list($a) = null;
var_dump($a);
?>
--EXPECT--
NULL

View File

@@ -0,0 +1,17 @@
--TEST--
Destructuring with list() a value of type object (that does not implement ArrayAccess)
--FILE--
<?php
$v = new stdClass();
list($a, $b) = $v;
var_dump($a, $b);
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View File

@@ -0,0 +1,18 @@
--TEST--
Destructuring with list() a value of type resource
--FILE--
<?php
$v = STDERR;
list($a, $b) = $v;
var_dump($a, $b);
?>
--EXPECTF--
Warning: Cannot use resource as array in %s on line %d
Warning: Cannot use resource as array in %s on line %d
NULL
NULL

View File

@@ -0,0 +1,21 @@
--TEST--
Destructuring with list() a value of type string
--FILE--
<?php
$v = 'hi';
list($a, $b, $c) = $v;
var_dump($a, $b, $c);
?>
--EXPECTF--
Warning: Cannot use string as array in %s on line %d
Warning: Cannot use string as array in %s on line %d
Warning: Cannot use string as array in %s on line %d
NULL
NULL
NULL

View File

@@ -1,24 +0,0 @@
--TEST--
list() with non-array
--FILE--
<?php
list($a) = NULL;
list($b) = 1;
list($c) = 1.;
list($d) = 'foo';
list($e) = print '';
var_dump($a, $b, $c, $d, $e);
?>
--EXPECT--
NULL
NULL
NULL
NULL
NULL

View File

@@ -1,50 +0,0 @@
--TEST--
Testing list() with several variables
--FILE--
<?php
$str = "foo";
list($a, $b, $c) = $str;
var_dump($a, $b, $c);
print "----\n";
$int = 1;
list($a, $b, $c) = $int;
var_dump($a, $b, $c);
print "----\n";
$obj = new stdClass;
list($a, $b, $c) = $obj;
var_dump($a, $b, $c);
print "----\n";
$arr = array(1, 2, 3);
list($a, $b, $c) = $arr;
var_dump($a, $b, $c);
?>
--EXPECTF--
NULL
NULL
NULL
----
NULL
NULL
NULL
----
Fatal error: Uncaught Error: Cannot use object of type stdClass as array in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View File

@@ -3005,7 +3005,7 @@ static zend_never_inline void ZEND_FASTCALL zend_fetch_dimension_address_UNSET(z
zend_fetch_dimension_address(result, container_ptr, dim, dim_type, BP_VAR_UNSET EXECUTE_DATA_CC);
}
static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, bool is_list, int slow EXECUTE_DATA_DC)
static zend_always_inline void zend_fetch_dimension_address_read(zval *result, zval *container, zval *dim, int dim_type, int type, bool is_list, bool slow EXECUTE_DATA_DC)
{
zval *retval;
@@ -3143,6 +3143,9 @@ try_string_offset:
if (ZEND_CONST_COND(dim_type == IS_CV, 1) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
ZVAL_UNDEFINED_OP2();
}
if (is_list && Z_TYPE_P(container) > IS_NULL) {
zend_error(E_WARNING, "Cannot use %s as array", zend_zval_type_name(container));
}
if (!is_list && type != BP_VAR_IS) {
zend_error(E_WARNING, "Trying to access array offset on %s",
zend_zval_value_name(container));

View File

@@ -16,6 +16,7 @@
+----------------------------------------------------------------------+
*/
#include "Zend/zend_types.h"
#include "Zend/zend_API.h"
static ZEND_COLD void undef_result_after_exception(void) {
@@ -2561,6 +2562,14 @@ static void ZEND_FASTCALL zend_jit_only_vars_by_reference(zval *arg)
zend_error(E_NOTICE, "Only variables should be passed by reference");
}
static void ZEND_FASTCALL zend_jit_invalid_array_use(const zval *container)
{
/* Warning should not occur on null */
if (Z_TYPE_P(container) != IS_NULL) {
zend_error(E_WARNING, "Cannot use %s as array", zend_zval_type_name(container));
}
}
static void ZEND_FASTCALL zend_jit_invalid_array_access(zval *container)
{
zend_error(E_WARNING, "Trying to access array offset on %s", zend_zval_value_name(container));

View File

@@ -16,6 +16,7 @@
* +----------------------------------------------------------------------+
*/
#include "Zend/zend_type_info.h"
#include "jit/ir/ir.h"
#include "jit/ir/ir_builder.h"
#include "jit/tls/zend_jit_tls.h"
@@ -12786,7 +12787,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit,
}
}
if (opline->opcode != ZEND_FETCH_DIM_IS && opline->opcode != ZEND_FETCH_LIST_R) {
if (opline->opcode != ZEND_FETCH_DIM_IS) {
ir_ref ref;
may_throw = 1;
@@ -12796,7 +12797,11 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit,
jit_SET_EX_OPLINE(jit, opline);
ref = jit_ZVAL_ADDR(jit, op1_addr);
}
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_invalid_array_access), ref);
if (opline->opcode == ZEND_FETCH_LIST_R) {
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_invalid_array_use), ref);
} else {
ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_invalid_array_access), ref);
}
}
jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL);

View File

@@ -13,5 +13,6 @@ function test() {
}
test();
?>
--EXPECT--
--EXPECTF--
Warning: Cannot use string as array in %s on line %d
NULL

View File

@@ -1,5 +1,5 @@
--TEST--
Block Pass 003: Inorrect constant substitution in FETCH_LIST_R
Block Pass 003: Incorrect constant substitution in FETCH_LIST_R
--INI--
opcache.enable=1
opcache.enable_cli=1
@@ -16,5 +16,44 @@ function test() {
test();
?>
DONE
--EXPECT--
--EXPECTF--
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
DONE

View File

@@ -116,6 +116,10 @@ array(3) {
int(3000)
}
L=100 M=200 N=300
Warning: Cannot use int as array in %s on line %d
Warning: Cannot use int as array in %s on line %d
O= and P=
10 20 40 50 60 70 80