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:
committed by
GitHub
parent
fc467dcb64
commit
8747e9ae18
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
18
Zend/tests/list/destruct_bool.phpt
Normal file
18
Zend/tests/list/destruct_bool.phpt
Normal 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
|
||||
18
Zend/tests/list/destruct_float.phpt
Normal file
18
Zend/tests/list/destruct_float.phpt
Normal 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
|
||||
18
Zend/tests/list/destruct_int.phpt
Normal file
18
Zend/tests/list/destruct_int.phpt
Normal 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
|
||||
12
Zend/tests/list/destruct_null.phpt
Normal file
12
Zend/tests/list/destruct_null.phpt
Normal file
@@ -0,0 +1,12 @@
|
||||
--TEST--
|
||||
Destructuring with list() a value of type null
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
list($a) = null;
|
||||
|
||||
var_dump($a);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
NULL
|
||||
17
Zend/tests/list/destruct_object_not_ArrayAccess.phpt
Normal file
17
Zend/tests/list/destruct_object_not_ArrayAccess.phpt
Normal 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
|
||||
18
Zend/tests/list/destruct_resource.phpt
Normal file
18
Zend/tests/list/destruct_resource.phpt
Normal 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
|
||||
21
Zend/tests/list/destruct_string.phpt
Normal file
21
Zend/tests/list/destruct_string.phpt
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -13,5 +13,6 @@ function test() {
|
||||
}
|
||||
test();
|
||||
?>
|
||||
--EXPECT--
|
||||
--EXPECTF--
|
||||
Warning: Cannot use string as array in %s on line %d
|
||||
NULL
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user