Skip to content

Commit 5459ed4

Browse files
committed
Fix use after free because of data clobbering by user error handler
Fixes oss-fuzz #41692
1 parent 4ed10f3 commit 5459ed4

File tree

5 files changed

+561
-196
lines changed

5 files changed

+561
-196
lines changed

Zend/tests/falsetoarray_002.phpt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Autovivification of false to array with data clobbering by error handler
3+
--FILE--
4+
<?php
5+
set_error_handler(function($code, $msg) {
6+
echo "Err: $msg\n";
7+
$GLOBALS['a']='';
8+
});
9+
$a=[!'a'];
10+
$a[0][$d]='b';
11+
var_dump($a);
12+
?>
13+
--EXPECT--
14+
Err: Automatic conversion of false to array is deprecated
15+
string(0) ""

Zend/zend_execute.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,13 +2508,24 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
25082508
if (type != BP_VAR_W && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
25092509
ZVAL_UNDEFINED_OP1();
25102510
}
2511-
if (Z_TYPE_P(container) == IS_FALSE) {
2512-
zend_false_to_array_deprecated();
2513-
}
25142511
if (type != BP_VAR_UNSET) {
2515-
array_init(container);
2512+
HashTable *ht = zend_new_array(0);
2513+
zend_uchar old_type = Z_TYPE_P(container);
2514+
2515+
ZVAL_ARR(container, ht);
2516+
if (UNEXPECTED(old_type == IS_FALSE)) {
2517+
GC_ADDREF(ht);
2518+
zend_false_to_array_deprecated();
2519+
if (UNEXPECTED(GC_DELREF(ht) == 0)) {
2520+
zend_array_destroy(ht);
2521+
goto return_null;
2522+
}
2523+
}
25162524
goto fetch_from_array;
25172525
} else {
2526+
if (UNEXPECTED(Z_TYPE_P(container) == IS_FALSE)) {
2527+
zend_false_to_array_deprecated();
2528+
}
25182529
return_null:
25192530
/* for read-mode only */
25202531
if (ZEND_CONST_COND(dim_type == IS_CV, dim != NULL) && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {

Zend/zend_vm_def.h

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,13 +1217,23 @@ ZEND_VM_C_LABEL(assign_dim_op_new_array):
12171217
}
12181218
zend_binary_assign_op_obj_dim(container, dim OPLINE_CC EXECUTE_DATA_CC);
12191219
} else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
1220+
HashTable *ht;
1221+
zend_uchar old_type;
1222+
12201223
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
12211224
ZVAL_UNDEFINED_OP1();
12221225
}
1223-
if (Z_TYPE_P(container) == IS_FALSE) {
1226+
ht = zend_new_array(8);
1227+
old_type = Z_TYPE_P(container);
1228+
ZVAL_ARR(container, ht);
1229+
if (UNEXPECTED(old_type == IS_FALSE)) {
1230+
GC_ADDREF(ht);
12241231
zend_false_to_array_deprecated();
1232+
if (UNEXPECTED(GC_DELREF(ht) == 0)) {
1233+
zend_array_destroy(ht);
1234+
ZEND_VM_C_GOTO(assign_dim_op_ret_null);
1235+
}
12251236
}
1226-
ZVAL_ARR(container, zend_new_array(8));
12271237
ZEND_VM_C_GOTO(assign_dim_op_new_array);
12281238
} else {
12291239
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
@@ -2626,18 +2636,25 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
26262636
FREE_OP_DATA();
26272637
}
26282638
} else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
2629-
if (Z_TYPE_P(object_ptr) == IS_FALSE) {
2630-
zend_false_to_array_deprecated();
2631-
}
2632-
26332639
if (Z_ISREF_P(orig_object_ptr)
26342640
&& ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr))
26352641
&& !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) {
26362642
dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
26372643
FREE_OP_DATA();
26382644
UNDEF_RESULT();
26392645
} else {
2640-
ZVAL_ARR(object_ptr, zend_new_array(8));
2646+
HashTable *ht = zend_new_array(8);
2647+
zend_uchar old_type = Z_TYPE_P(object_ptr);
2648+
2649+
ZVAL_ARR(object_ptr, ht);
2650+
if (UNEXPECTED(old_type == IS_FALSE)) {
2651+
GC_ADDREF(ht);
2652+
zend_false_to_array_deprecated();
2653+
if (UNEXPECTED(GC_DELREF(ht) == 0)) {
2654+
zend_array_destroy(ht);
2655+
ZEND_VM_C_GOTO(assign_dim_error);
2656+
}
2657+
}
26412658
ZEND_VM_C_GOTO(try_assign_dim_array);
26422659
}
26432660
} else {

0 commit comments

Comments
 (0)