Skip to content
Closed
4 changes: 2 additions & 2 deletions Zend/Optimizer/zend_inference.c
Original file line number Diff line number Diff line change
Expand Up @@ -4753,7 +4753,7 @@ ZEND_API int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op,
return 1;
}
}
return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_TRUE|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)) || opline->op2_type == IS_UNUSED ||
return (t1 & (MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_TRUE|MAY_BE_FALSE|MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE)) || opline->op2_type == IS_UNUSED ||
(t2 & (MAY_BE_UNDEF|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE));
case ZEND_ASSIGN_OBJ:
if (t1 & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_OBJECT))) {
Expand Down Expand Up @@ -4869,7 +4869,7 @@ ZEND_API int zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op,
return 0;
case ZEND_FETCH_DIM_W:
case ZEND_FETCH_LIST_W:
if (t1 & (MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
if (t1 & (MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
return 1;
}
if (t2 & (MAY_BE_RESOURCE|MAY_BE_ARRAY|MAY_BE_OBJECT)) {
Expand Down
194 changes: 194 additions & 0 deletions Zend/tests/falsetoarray.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
--TEST--
Autovivification of false to array
--FILE--
<?php

// control
$undef[] = 42;

// control
$null = null;
$null[] = 42;

// control
$false = false;
$false = [42];

print "[001]\n";
$false = false;
$false[] = 42;

print "[002]\n";
$ref = false;
$ref2 = &$ref;
$ref2[] = 42;

echo "\nFunction\n";
function ffalse(bool $a, ?bool $b, &$c, ...$d) {
print "[003]\n";
$a[] = 42;
print "[004]\n";
$b[] = 42;
print "[005]\n";
$c[] = 42;
print "[006]\n";
$d[0][] = 42;
}
$ref = false;
ffalse(false, false, $ref, false);

echo "\nProperties\n";
class Cfalse {
public $def;
private $untyped = false;
static private $st = false;
static private $st2 = false;
static private $st3 = false;
public function __construct(public $pu, private $pr = false) {
print "[007]\n";
$this->def = false;
$this->def[] = 42;
print "[008]\n";
$this->untyped[] = 42;
print "[009]\n";
self::$st[] = 42;
print "[010]\n";
static::$st2[] = 42;
print "[011]\n";
$this::$st3[] = 42;
print "[012]\n";
$this->pu[] = 42;
print "[013]\n";
$this->pr[] = 42;
}
}
new Cfalse(false, false);

echo "\nDestructuring\n";

print "[014]\n";
$add = false;
foreach ([42] as $add[]);

print "[015]\n";
$arr = false;
[$arr[]] = [42];

print "[016]\n";
$arr = [ 0 => [ 0 => false ] ];
$arr[0][0][0][] = 42;

print "[017]\n";
$false = false;
$r42 = 42;
$false[] &= $r42;

$false = false;
$false2 = false;
$false3 = false;
function &g(){
print "[018]\n";
global $false;
$false[] = 42;

$var1 = false;
$GLOBALS["false2"] =& $var1;

print "[019]\n";
$GLOBALS["false3"][] = 42;

print "[020]\n";
static $f2 = false;
return $f2;
}

$false = &g();
$false[] = 42;
print "[021]\n";
$false2[] = 42;

print "[022]\n";
$a = false;
unset($a[0][0]);

print "[023]\n";
$a = false;
unset($a[0]);

?>
--EXPECTF--
[001]

Deprecated: Automatic conversion of false to array is deprecated in %s
[002]

Deprecated: Automatic conversion of false to array is deprecated in %s

Function
[003]

Deprecated: Automatic conversion of false to array is deprecated in %s
[004]

Deprecated: Automatic conversion of false to array is deprecated in %s
[005]

Deprecated: Automatic conversion of false to array is deprecated in %s
[006]

Deprecated: Automatic conversion of false to array is deprecated in %s

Properties
[007]

Deprecated: Automatic conversion of false to array is deprecated in %s
[008]

Deprecated: Automatic conversion of false to array is deprecated in %s
[009]

Deprecated: Automatic conversion of false to array is deprecated in %s
[010]

Deprecated: Automatic conversion of false to array is deprecated in %s
[011]

Deprecated: Automatic conversion of false to array is deprecated in %s
[012]

Deprecated: Automatic conversion of false to array is deprecated in %s
[013]

Deprecated: Automatic conversion of false to array is deprecated in %s

Destructuring
[014]

Deprecated: Automatic conversion of false to array is deprecated in %s
[015]

Deprecated: Automatic conversion of false to array is deprecated in %s
[016]

Deprecated: Automatic conversion of false to array is deprecated in %s
[017]

Deprecated: Automatic conversion of false to array is deprecated in %s
[018]

Deprecated: Automatic conversion of false to array is deprecated in %s
[019]

Deprecated: Automatic conversion of false to array is deprecated in %s
[020]

Deprecated: Automatic conversion of false to array is deprecated in %s
[021]

Deprecated: Automatic conversion of false to array is deprecated in %s
[022]

Deprecated: Automatic conversion of false to array is deprecated in %s
[023]

Deprecated: Automatic conversion of false to array is deprecated in %s
10 changes: 9 additions & 1 deletion Zend/tests/indexing_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ foreach ($testvalues as $testvalue) {
}

?>
--EXPECT--
--EXPECTF--
*** Indexing - Testing value assignment with key ***
array(1) {
["foo"]=>
Expand All @@ -67,6 +67,8 @@ Cannot use a scalar value as an array
int(1)
Cannot use a scalar value as an array
bool(true)

Deprecated: Automatic conversion of false to array is deprecated in %s
array(1) {
["foo"]=>
array(1) {
Expand Down Expand Up @@ -102,6 +104,8 @@ Cannot use a scalar value as an array
int(1)
Cannot use a scalar value as an array
bool(true)

Deprecated: Automatic conversion of false to array is deprecated in %s
array(1) {
["foo"]=>
&array(1) {
Expand Down Expand Up @@ -132,6 +136,8 @@ Cannot use a scalar value as an array
int(1)
Cannot use a scalar value as an array
bool(true)

Deprecated: Automatic conversion of false to array is deprecated in %s
array(1) {
[0]=>
array(1) {
Expand Down Expand Up @@ -163,6 +169,8 @@ Cannot use a scalar value as an array
int(1)
Cannot use a scalar value as an array
bool(true)

Deprecated: Automatic conversion of false to array is deprecated in %s
array(1) {
[0]=>
&array(1) {
Expand Down
4 changes: 4 additions & 0 deletions Zend/tests/unset_non_array.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,17 @@ try {
?>
--EXPECTF--
Warning: Undefined variable $x in %s on line %d

Deprecated: Automatic conversion of false to array is deprecated in %s
Cannot unset offset in a non-array variable
Cannot unset offset in a non-array variable
Cannot unset offset in a non-array variable
Cannot unset string offsets
Cannot use object of type stdClass as array

Warning: Undefined variable $x in %s on line %d

Deprecated: Automatic conversion of false to array is deprecated in %s
Cannot unset offset in a non-array variable
Cannot unset offset in a non-array variable
Cannot unset offset in a non-array variable
Expand Down
8 changes: 8 additions & 0 deletions Zend/zend_execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,11 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_functi
}
}

ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void)
{
zend_error(E_DEPRECATED, "Automatic conversion of false to array is deprecated");
}

static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim, zval *value OPLINE_DC EXECUTE_DATA_DC)
{
zend_uchar c;
Expand Down Expand Up @@ -2330,6 +2335,9 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
ZVAL_UNDEFINED_OP1();
}
if (Z_TYPE_P(container) == IS_FALSE) {
zend_false_to_array_deprecated();
}
if (type != BP_VAR_UNSET) {
array_init(container);
goto fetch_from_array;
Expand Down
1 change: 1 addition & 0 deletions Zend/zend_execute.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extern ZEND_API const zend_internal_function zend_pass_function;

ZEND_API ZEND_COLD void ZEND_FASTCALL zend_missing_arg_error(zend_execute_data *execute_data);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_deprecated_function(const zend_function *fbc);
ZEND_API ZEND_COLD void ZEND_FASTCALL zend_false_to_array_deprecated(void);
ZEND_COLD void ZEND_FASTCALL zend_param_must_be_ref(const zend_function *func, uint32_t arg_num);

ZEND_API bool ZEND_FASTCALL zend_verify_ref_assignable_zval(zend_reference *ref, zval *zv, bool strict);
Expand Down
9 changes: 9 additions & 0 deletions Zend/zend_vm_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -1210,6 +1210,9 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
ZVAL_UNDEFINED_OP1();
}
if (Z_TYPE_P(container) == IS_FALSE) {
zend_false_to_array_deprecated();
}
ZVAL_ARR(container, zend_new_array(8));
ZEND_VM_C_GOTO(assign_dim_op_new_array);
} else {
Expand Down Expand Up @@ -2590,6 +2593,10 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
FREE_OP_DATA();
}
} else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
if (Z_TYPE_P(object_ptr) == IS_FALSE) {
zend_false_to_array_deprecated();
}

if (Z_ISREF_P(orig_object_ptr)
&& ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr))
&& !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) {
Expand Down Expand Up @@ -6453,6 +6460,8 @@ ZEND_VM_C_LABEL(num_index_dim):
zend_throw_error(NULL, "Cannot unset string offsets");
} else if (UNEXPECTED(Z_TYPE_P(container) > IS_FALSE)) {
zend_throw_error(NULL, "Cannot unset offset in a non-array variable");
} else if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) {
zend_false_to_array_deprecated();
}
} while (0);

Expand Down
Loading