1
0
mirror of https://github.com/php/php-src.git synced 2026-04-06 15:43:13 +02:00

Merge branch 'PHP-8.1'

* PHP-8.1:
  Fix use after free because of data clobbering by user error handler
This commit is contained in:
Dmitry Stogov
2021-12-06 13:09:26 +03:00
5 changed files with 561 additions and 196 deletions

View File

@@ -0,0 +1,15 @@
--TEST--
Autovivification of false to array with data clobbering by error handler
--FILE--
<?php
set_error_handler(function($code, $msg) {
echo "Err: $msg\n";
$GLOBALS['a']='';
});
$a=[!'a'];
$a[0][$d]='b';
var_dump($a);
?>
--EXPECT--
Err: Automatic conversion of false to array is deprecated
string(0) ""

View File

@@ -2434,13 +2434,24 @@ fetch_from_array:
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);
HashTable *ht = zend_new_array(0);
zend_uchar old_type = Z_TYPE_P(container);
ZVAL_ARR(container, ht);
if (UNEXPECTED(old_type == IS_FALSE)) {
GC_ADDREF(ht);
zend_false_to_array_deprecated();
if (UNEXPECTED(GC_DELREF(ht) == 0)) {
zend_array_destroy(ht);
goto return_null;
}
}
goto fetch_from_array;
} else {
if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) {
zend_false_to_array_deprecated();
}
return_null:
/* for read-mode only */
if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {

View File

@@ -1217,13 +1217,23 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
}
zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC);
} else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
HashTable *ht;
zend_uchar old_type;
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
ZVAL_UNDEFINED_OP1();
}
if (Z_TYPE_P(container) == IS_FALSE) {
ht = zend_new_array(8);
old_type = Z_TYPE_P(container);
ZVAL_ARR(container, ht);
if (UNEXPECTED(old_type == IS_FALSE)) {
GC_ADDREF(ht);
zend_false_to_array_deprecated();
if (UNEXPECTED(GC_DELREF(ht) == 0)) {
zend_array_destroy(ht);
ZEND_VM_C_GOTO(assign_dim_op_ret_null);
}
}
ZVAL_ARR(container, zend_new_array(8));
ZEND_VM_C_GOTO(assign_dim_op_new_array);
} else {
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
@@ -2635,10 +2645,6 @@ 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))) {
@@ -2646,7 +2652,18 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
FREE_OP_DATA();
UNDEF_RESULT();
} else {
ZVAL_ARR(object_ptr, zend_new_array(8));
HashTable *ht = zend_new_array(8);
zend_uchar old_type = Z_TYPE_P(object_ptr);
ZVAL_ARR(object_ptr, ht);
if (UNEXPECTED(old_type == IS_FALSE)) {
GC_ADDREF(ht);
zend_false_to_array_deprecated();
if (UNEXPECTED(GC_DELREF(ht) == 0)) {
zend_array_destroy(ht);
ZEND_VM_C_GOTO(assign_dim_error);
}
}
ZEND_VM_C_GOTO(try_assign_dim_array);
}
} else {

File diff suppressed because it is too large Load Diff

View File

@@ -1152,9 +1152,15 @@ static zend_always_inline void ZEND_FASTCALL zend_jit_fetch_dim_obj_helper(zval
}
ZVAL_UNDEF(result);
} else if (Z_TYPE_P(object_ptr) == IS_FALSE) {
zend_false_to_array_deprecated();
zend_array *arr = zend_new_array(0);
ZVAL_ARR(object_ptr, arr);
GC_ADDREF(arr);
zend_false_to_array_deprecated();
if (UNEXPECTED(GC_DELREF(arr) == 0)) {
zend_array_destroy(arr);
ZVAL_NULL(result);
return;
}
zval *var;
if (dim) {
if (type == BP_VAR_W) {
@@ -1247,12 +1253,6 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim
return;
}
if (dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
const zend_op *opline = EG(current_execute_data)->opline;
zend_jit_undefined_op_helper(opline->op2.var);
dim = &EG(uninitialized_zval);
}
if (UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
const zend_op *op_data = EG(current_execute_data)->opline + 1;
ZEND_ASSERT(op_data->opcode == ZEND_OP_DATA && op_data->op1_type == IS_CV);
@@ -1266,9 +1266,17 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim
ZVAL_UNDEF(result);
}
} else if (Z_TYPE_P(object_ptr) == IS_FALSE) {
zend_false_to_array_deprecated();
zend_array *arr = zend_new_array(0);
ZVAL_ARR(object_ptr, arr);
GC_ADDREF(arr);
zend_false_to_array_deprecated();
if (UNEXPECTED(GC_DELREF(arr) == 0)) {
zend_array_destroy(arr);
if (result) {
ZVAL_NULL(result);
}
return;
}
zval *var = dim
? zend_jit_fetch_dim_w_helper(arr, dim)
: zend_hash_next_index_insert_new(arr, &EG(uninitialized_zval));
@@ -1284,6 +1292,11 @@ static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim
ZVAL_COPY(result, var);
}
} else {
if (dim && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
const zend_op *opline = EG(current_execute_data)->opline;
zend_jit_undefined_op_helper(opline->op2.var);
dim = &EG(uninitialized_zval);
}
zend_throw_error(NULL, "Cannot use a scalar value as an array");
if (result) {
ZVAL_UNDEF(result);
@@ -1335,9 +1348,14 @@ static void ZEND_FASTCALL zend_jit_assign_dim_op_helper(zval *container, zval *d
zend_wrong_string_offset_error();
}
} else if (Z_TYPE_P(container) == IS_FALSE) {
zend_false_to_array_deprecated();
zend_array *arr = zend_new_array(0);
ZVAL_ARR(container, arr);
GC_ADDREF(arr);
zend_false_to_array_deprecated();
if (UNEXPECTED(GC_DELREF(arr) == 0)) {
zend_array_destroy(arr);
return;
}
zval *var = dim
? zend_jit_fetch_dim_rw_helper(arr, dim)
: zend_hash_next_index_insert_new(arr, &EG(uninitialized_zval));