From 4fd93a4da6270342cb15d46c9fb22bb630f6f502 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 1 Apr 2015 14:50:09 +0300 Subject: [PATCH] Converted fatal errors into EngineExceptions --- Zend/tests/exception_015.phpt | 17 ++++ Zend/zend_execute.c | 23 +++-- Zend/zend_vm_def.h | 21 +++-- Zend/zend_vm_execute.h | 156 +++++++++++++++++++++++----------- 4 files changed, 151 insertions(+), 66 deletions(-) create mode 100644 Zend/tests/exception_015.phpt diff --git a/Zend/tests/exception_015.phpt b/Zend/tests/exception_015.phpt new file mode 100644 index 00000000000..033848950eb --- /dev/null +++ b/Zend/tests/exception_015.phpt @@ -0,0 +1,17 @@ +--TEST-- +Exceptions on improper access to string +--FILE-- +getMessage() . " in " , $e->getFile() . " on line " . $e->getLine() . "\n"; +} + +$s[] = "D"; +?> +--EXPECTF-- +Exception: [] operator not supported for strings in %sexception_015.php on line %d + +Fatal error: [] operator not supported for strings in %sexception_015.php on line %d diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 384476478a1..7b7b4b528be 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1124,7 +1124,9 @@ static zend_never_inline void zend_assign_to_object_dim(zval *retval, zval *obje /* Note: property_name in this case is really the array index! */ if (!Z_OBJ_HT_P(object)->write_dimension) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + FREE_OP(free_value); + return; } /* separate our value if necessary */ @@ -1395,10 +1397,6 @@ static zend_never_inline zend_long zend_check_string_offset(zval *dim, int type) { zend_long offset; - if (dim == NULL) { - zend_error_noreturn(E_ERROR, "[] operator not supported for strings"); - } - try_again: if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) { switch(Z_TYPE_P(dim)) { @@ -1473,12 +1471,17 @@ convert_to_array: goto fetch_from_array; } - zend_check_string_offset(dim, type); + if (dim == NULL) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + } else { + zend_check_string_offset(dim, type); + } ZVAL_INDIRECT(result, NULL); /* wrong string offset */ } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (!Z_OBJ_HT_P(container)->read_dimension) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + retval = &EG(error_zval); } else { retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result); @@ -1610,7 +1613,8 @@ try_string_offset: } } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (!Z_OBJ_HT_P(container)->read_dimension) { - zend_error_noreturn(E_ERROR, "Cannot use object as array"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array"); + ZVAL_NULL(result); } else { retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result); @@ -1704,7 +1708,8 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c ZVAL_INDIRECT(result, ptr); } } else { - zend_error_noreturn(E_ERROR, "Cannot access undefined property for object with overloaded property access"); + zend_error(E_EXCEPTION | E_ERROR, "Cannot access undefined property for object with overloaded property access"); + ZVAL_INDIRECT(result, &EG(error_zval)); } } else { ZVAL_INDIRECT(result, ptr); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c8270e8c056..350833655fd 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2136,14 +2136,21 @@ ZEND_VM_C_LABEL(try_assign_dim_array): FREE_OP2(); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if (OP2_TYPE == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_OP1_VAR_PTR(); + HANDLE_EXCEPTION(); + } else { + zend_long offset; - dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - FREE_OP2(); - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + dim = GET_OP2_ZVAL_PTR(BP_VAR_R); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + FREE_OP2(); + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); ZEND_VM_C_LABEL(assign_dim_convert_to_array): diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 70035b1cad3..77c2002cb44 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -15705,14 +15705,21 @@ try_assign_dim_array: } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if (IS_CONST == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; - dim = EX_CONSTANT(opline->op2); - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: @@ -17307,14 +17314,21 @@ try_assign_dim_array: } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if (IS_UNUSED == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; - dim = NULL; - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: @@ -18824,14 +18838,21 @@ try_assign_dim_array: } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if (IS_CV == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; - dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: @@ -20473,14 +20494,21 @@ try_assign_dim_array: zval_ptr_dtor_nogc(free_op2); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (free_op1) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; - dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: @@ -29411,14 +29439,21 @@ try_assign_dim_array: } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if (IS_CONST == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); - dim = EX_CONSTANT(opline->op2); - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + HANDLE_EXCEPTION(); + } else { + zend_long offset; - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: @@ -32011,14 +32046,21 @@ try_assign_dim_array: } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if (IS_UNUSED == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); - dim = NULL; - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + HANDLE_EXCEPTION(); + } else { + zend_long offset; - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: @@ -34189,14 +34231,21 @@ try_assign_dim_array: } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if (IS_CV == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); - dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + HANDLE_EXCEPTION(); + } else { + zend_long offset; - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: @@ -36700,14 +36749,21 @@ try_assign_dim_array: zval_ptr_dtor_nogc(free_op2); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { - zend_long offset; + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings"); + FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); - dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); - zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); assign_dim_convert_to_array: