mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Prevent array modification if it's captured by user error handler during
index conversion Fixes oss-fuzz #44235
This commit is contained in:
parent
8e2406c59b
commit
718478377b
18
Zend/tests/array_offset_002.phpt
Normal file
18
Zend/tests/array_offset_002.phpt
Normal file
@ -0,0 +1,18 @@
|
||||
--TEST--
|
||||
Capturing array in user error handler during index conversion
|
||||
--FILE--
|
||||
<?php
|
||||
set_error_handler(function($code, $msg) {
|
||||
echo "Err: $msg\n";
|
||||
$GLOBALS[''] = $GLOBALS['y'];
|
||||
});
|
||||
function x(&$s){
|
||||
$s[100000000000000000000] = 1;
|
||||
}
|
||||
x($y);
|
||||
var_dump($y);
|
||||
?>
|
||||
--EXPECT--
|
||||
Err: Implicit conversion from float 1.0E+20 to int loses precision
|
||||
array(0) {
|
||||
}
|
@ -2147,8 +2147,10 @@ ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_offset_write(HashTable *ht
|
||||
GC_ADDREF(ht);
|
||||
}
|
||||
zend_undefined_offset(lval);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
if (EG(exception)) {
|
||||
@ -2169,8 +2171,10 @@ ZEND_API ZEND_COLD zval* ZEND_FASTCALL zend_undefined_index_write(HashTable *ht,
|
||||
/* Key may be released while throwing the undefined index warning. */
|
||||
zend_string_addref(offset);
|
||||
zend_undefined_index(offset);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
retval = NULL;
|
||||
} else if (EG(exception)) {
|
||||
retval = NULL;
|
||||
@ -2319,6 +2323,80 @@ static zend_never_inline zend_uchar slow_index_convert(HashTable *ht, const zval
|
||||
}
|
||||
}
|
||||
|
||||
static zend_never_inline zend_uchar slow_index_convert_w(HashTable *ht, const zval *dim, zend_value *value EXECUTE_DATA_DC)
|
||||
{
|
||||
switch (Z_TYPE_P(dim)) {
|
||||
case IS_UNDEF: {
|
||||
/* The array may be destroyed while throwing the notice.
|
||||
* Temporarily increase the refcount to detect this situation. */
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
|
||||
GC_ADDREF(ht);
|
||||
}
|
||||
ZVAL_UNDEFINED_OP2();
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
return IS_NULL;
|
||||
}
|
||||
if (EG(exception)) {
|
||||
return IS_NULL;
|
||||
}
|
||||
ZEND_FALLTHROUGH;
|
||||
}
|
||||
case IS_NULL:
|
||||
value->str = ZSTR_EMPTY_ALLOC();
|
||||
return IS_STRING;
|
||||
case IS_DOUBLE:
|
||||
value->lval = zend_dval_to_lval(Z_DVAL_P(dim));
|
||||
if (!zend_is_long_compatible(Z_DVAL_P(dim), value->lval)) {
|
||||
/* The array may be destroyed while throwing the notice.
|
||||
* Temporarily increase the refcount to detect this situation. */
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
|
||||
GC_ADDREF(ht);
|
||||
}
|
||||
zend_incompatible_double_to_long_error(Z_DVAL_P(dim));
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
return IS_NULL;
|
||||
}
|
||||
if (EG(exception)) {
|
||||
return IS_NULL;
|
||||
}
|
||||
}
|
||||
return IS_LONG;
|
||||
case IS_RESOURCE:
|
||||
/* The array may be destroyed while throwing the notice.
|
||||
* Temporarily increase the refcount to detect this situation. */
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) {
|
||||
GC_ADDREF(ht);
|
||||
}
|
||||
zend_use_resource_as_offset(dim);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
return IS_NULL;
|
||||
}
|
||||
if (EG(exception)) {
|
||||
return IS_NULL;
|
||||
}
|
||||
value->lval = Z_RES_HANDLE_P(dim);
|
||||
return IS_LONG;
|
||||
case IS_FALSE:
|
||||
value->lval = 0;
|
||||
return IS_LONG;
|
||||
case IS_TRUE:
|
||||
value->lval = 1;
|
||||
return IS_LONG;
|
||||
default:
|
||||
zend_illegal_offset();
|
||||
return IS_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static zend_always_inline zval *zend_fetch_dimension_address_inner(HashTable *ht, const zval *dim, int dim_type, int type EXECUTE_DATA_DC)
|
||||
{
|
||||
zval *retval = NULL;
|
||||
@ -2380,8 +2458,13 @@ str_index:
|
||||
goto try_again;
|
||||
} else {
|
||||
zend_value val;
|
||||
zend_uchar t = slow_index_convert(ht, dim, &val EXECUTE_DATA_CC);
|
||||
zend_uchar t;
|
||||
|
||||
if (type != BP_VAR_W && type != BP_VAR_RW) {
|
||||
t = slow_index_convert(ht, dim, &val EXECUTE_DATA_CC);
|
||||
} else {
|
||||
t = slow_index_convert_w(ht, dim, &val EXECUTE_DATA_CC);
|
||||
}
|
||||
if (t == IS_STRING) {
|
||||
offset_key = val.str;
|
||||
goto str_index;
|
||||
|
@ -365,8 +365,10 @@ static int ZEND_FASTCALL zend_jit_undefined_op_helper_write(HashTable *ht, uint3
|
||||
GC_ADDREF(ht);
|
||||
}
|
||||
zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(cv));
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return EG(exception) == NULL;
|
||||
@ -808,8 +810,10 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di
|
||||
execute_data = EG(current_execute_data);
|
||||
opline = EX(opline);
|
||||
zend_incompatible_double_to_long_error(Z_DVAL_P(dim));
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
|
||||
if (EG(exception)) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
@ -836,8 +840,10 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_rw_helper(zend_array *ht, zval *di
|
||||
execute_data = EG(current_execute_data);
|
||||
opline = EX(opline);
|
||||
zend_use_resource_as_offset(dim);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
|
||||
if (EG(exception)) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
@ -933,8 +939,10 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_w_helper(zend_array *ht, zval *dim
|
||||
execute_data = EG(current_execute_data);
|
||||
opline = EX(opline);
|
||||
zend_incompatible_double_to_long_error(Z_DVAL_P(dim));
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
|
||||
if (EG(exception)) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
@ -961,8 +969,10 @@ static zval* ZEND_FASTCALL zend_jit_fetch_dim_w_helper(zend_array *ht, zval *dim
|
||||
execute_data = EG(current_execute_data);
|
||||
opline = EX(opline);
|
||||
zend_use_resource_as_offset(dim);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && !GC_DELREF(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE) && GC_DELREF(ht) != 1) {
|
||||
if (!GC_REFCOUNT(ht)) {
|
||||
zend_array_destroy(ht);
|
||||
}
|
||||
if (opline->result_type & (IS_VAR | IS_TMP_VAR)) {
|
||||
if (EG(exception)) {
|
||||
ZVAL_UNDEF(EX_VAR(opline->result.var));
|
||||
|
Loading…
Reference in New Issue
Block a user