Skip to content

Commit

Permalink
Fix use after free because of data clobbering by user error handler
Browse files Browse the repository at this point in the history
Fixes oss-fuzz #41692
  • Loading branch information
dstogov committed Dec 6, 2021
1 parent 4ed10f3 commit 5459ed4
Show file tree
Hide file tree
Showing 5 changed files with 561 additions and 196 deletions.
15 changes: 15 additions & 0 deletions Zend/tests/falsetoarray_002.phpt
@@ -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) ""
19 changes: 15 additions & 4 deletions Zend/zend_execute.c
Expand Up @@ -2508,13 +2508,24 @@ 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);
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)) {
Expand Down
31 changes: 24 additions & 7 deletions Zend/zend_vm_def.h
Expand Up @@ -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);
Expand Down Expand Up @@ -2626,18 +2636,25 @@ 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))) {
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
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 {
Expand Down

0 comments on commit 5459ed4

Please sign in to comment.