diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index 61c8f420aa43f..b1ce7642fe882 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -568,6 +568,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array if (opline->op1_type == IS_CONST) { ++(*opt_count); block->successors_count = 1; + /* zend_is_true() cannot fail here as op1 cannot be an object */ if (zend_is_true(&ZEND_OP1_LITERAL(opline)) == (opline->opcode == ZEND_JMPZ)) { @@ -617,6 +618,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array while (1) { if (opline->op1_type == IS_CONST) { ++(*opt_count); + /* zend_is_true() cannot fail here as op1 cannot be an object */ if (zend_is_true(&ZEND_OP1_LITERAL(opline))) { zend_op *target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline); diff --git a/Zend/Optimizer/dfa_pass.c b/Zend/Optimizer/dfa_pass.c index 2967addd2f0bf..e8851cece4c74 100644 --- a/Zend/Optimizer/dfa_pass.c +++ b/Zend/Optimizer/dfa_pass.c @@ -397,6 +397,7 @@ int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa) send_array = call_info->caller_call_opline - 1; send_needly = call_info->caller_call_opline - 2; } else { + /* zend_is_true() cannot fail here as op1 is not an object */ if (zend_is_true(CT_CONSTANT_EX(op_array, (call_info->caller_call_opline - 1)->op1.constant))) { strict = 1; } diff --git a/Zend/Optimizer/pass1.c b/Zend/Optimizer/pass1.c index 1f0dbea5c65a0..d041df82a11cb 100644 --- a/Zend/Optimizer/pass1.c +++ b/Zend/Optimizer/pass1.c @@ -595,6 +595,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) /* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C) in case we know it wouldn't jump */ if (opline->op1_type == IS_CONST) { + /* zend_is_true() cannot fail here as op1 is not an object */ if (zend_is_true(&ZEND_OP1_LITERAL(opline))) { if (opline->opcode == ZEND_JMPZ_EX) { opline->opcode = ZEND_QM_ASSIGN; @@ -619,6 +620,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) case ZEND_JMPZ: case ZEND_JMPNZ: if (opline->op1_type == IS_CONST) { + /* zend_is_true() cannot fail here as op1 is not an object */ int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline)); if (opline->opcode == ZEND_JMPZ) { @@ -642,6 +644,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx) if (opline->op1_type == IS_CONST) { zend_op *target_opline; + /* zend_is_true() cannot fail here as op1 is not an object */ if (zend_is_true(&ZEND_OP1_LITERAL(opline))) { target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); /* JMPNZ */ } else { diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c index 342de0bdacdb0..e8a3527f8d2c8 100644 --- a/Zend/Optimizer/sccp.c +++ b/Zend/Optimizer/sccp.c @@ -391,6 +391,7 @@ static inline int ct_eval_bool_cast(zval *result, zval *op) { return SUCCESS; } + /* op cannot be an object so zend_is_true() cannot fail */ ZVAL_BOOL(result, zend_is_true(op)); return SUCCESS; } diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index 66a27bd9c7416..8458dbb73aa5a 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -79,6 +79,9 @@ int zend_optimizer_eval_unary_op(zval *result, zend_uchar opcode, zval *op1) /* return unary_op(result, op1); } else { /* ZEND_BOOL */ ZVAL_BOOL(result, zend_is_true(op1)); + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } return SUCCESS; } } diff --git a/Zend/tests/temporary_cleaning_014.phpt b/Zend/tests/temporary_cleaning_014.phpt index 732ac1303072e..33246d6d02a07 100644 --- a/Zend/tests/temporary_cleaning_014.phpt +++ b/Zend/tests/temporary_cleaning_014.phpt @@ -4,10 +4,10 @@ Leak in JMP_SET gmp --FILE-- DONE diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 57e0a406e458d..3dda4869dd848 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -474,6 +474,10 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(zval *arg, bool *dest, uint return 0; } *dest = zend_is_true(arg); + /* arg is an object which cannot be converted to bool */ + if (UNEXPECTED(EG(exception))) { + return 0; + } } else { return 0; } diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c index ba46b7feb6cba..063ae216fd8b1 100644 --- a/Zend/zend_ast.c +++ b/Zend/zend_ast.c @@ -604,8 +604,18 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast break; } ZVAL_BOOL(result, zend_is_true(&op2)); + /* op2 is an object which cannot be converted to bool */ + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(result); + return FAILURE; + } zval_ptr_dtor_nogc(&op2); } else { + /* op1 is an object which cannot be converted to bool */ + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(result); + return FAILURE; + } ZVAL_FALSE(result); } zval_ptr_dtor_nogc(&op1); @@ -618,12 +628,22 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast if (zend_is_true(&op1)) { ZVAL_TRUE(result); } else { + /* op1 is an object which cannot be converted to bool */ + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(result); + return FAILURE; + } if (UNEXPECTED(zend_ast_evaluate(&op2, ast->child[1], scope) != SUCCESS)) { zval_ptr_dtor_nogc(&op1); ret = FAILURE; break; } ZVAL_BOOL(result, zend_is_true(&op2)); + /* op2 is an object which cannot be converted to bool */ + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(result); + return FAILURE; + } zval_ptr_dtor_nogc(&op2); } zval_ptr_dtor_nogc(&op1); @@ -645,6 +665,10 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate(zval *result, zend_ast *ast zval_ptr_dtor_nogc(&op1); } } else { + /* op1 is an object which cannot be converted to bool */ + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } if (UNEXPECTED(zend_ast_evaluate(result, ast->child[2], scope) != SUCCESS)) { zval_ptr_dtor_nogc(&op1); ret = FAILURE; diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 100ac6563cb13..47db1da849813 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -8320,7 +8320,8 @@ ZEND_API bool zend_unary_op_produces_error(uint32_t opcode, zval *op) return Z_TYPE_P(op) <= IS_TRUE || !zend_is_op_long_compatible(op); } - return 0; + /* Objects might throw a type error if they cannot be converted to bool */ + return Z_TYPE_P(op) == IS_OBJECT; } static inline bool zend_try_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */ @@ -10165,6 +10166,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ } child0_is_true = zend_is_true(zend_ast_get_zval(ast->child[0])); + /* TODO Check if need to handle potential TypeError if child[0] is an object which cannot be converted to bool */ if (child0_is_true == (ast->kind == ZEND_AST_OR)) { ZVAL_BOOL(&result, ast->kind == ZEND_AST_OR); break; @@ -10175,6 +10177,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ } child1_is_true = zend_is_true(zend_ast_get_zval(ast->child[1])); + /* TODO Check if need to handle potential TypeError if child[1] is an object which cannot be converted to bool */ if (ast->kind == ZEND_AST_OR) { ZVAL_BOOL(&result, child0_is_true || child1_is_true); } else { @@ -10241,6 +10244,7 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */ } child = &ast->child[2 - zend_is_true(zend_ast_get_zval(ast->child[0]))]; + /* TODO Check if need to handle potential TypeError if child[0] is an object which cannot be converted to bool */ if (*child == NULL) { child--; } diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index c348152d6a985..82efc03f7ea89 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -634,6 +634,7 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int *guard &= ~IN_ISSET; if (!zend_is_true(&tmp_result)) { + /* handles case when tmp_result is an object which cannot be converted to bool */ retval = &EG(uninitialized_zval); OBJ_RELEASE(zobj); zval_ptr_dtor(&tmp_result); @@ -851,6 +852,7 @@ ZEND_API zval *zend_std_read_dimension(zend_object *object, zval *offset, int ty return NULL; } if (!i_zend_is_true(rv)) { + /* handles case when tmp_result is an object which cannot be converted to bool */ OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); zval_ptr_dtor(rv); @@ -909,12 +911,14 @@ ZEND_API int zend_std_has_dimension(zend_object *object, zval *offset, int check ZVAL_COPY_DEREF(&tmp_offset, offset); GC_ADDREF(object); zend_call_method_with_1_params(object, ce, NULL, "offsetexists", &retval, &tmp_offset); + ZEND_ASSERT(Z_TYPE(retval) != IS_OBJECT); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); if (check_empty && result && EXPECTED(!EG(exception))) { zend_call_method_with_1_params(object, ce, NULL, "offsetget", &retval, &tmp_offset); result = i_zend_is_true(&retval); zval_ptr_dtor(&retval); + /* TODO: need to do something if retval is an object which cannot be converted to bool? */ } OBJ_RELEASE(object); zval_ptr_dtor(&tmp_offset); @@ -1676,6 +1680,7 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has found: if (has_set_exists == ZEND_PROPERTY_NOT_EMPTY) { result = zend_is_true(value); + /* TODO: need to do something if retval is an object which cannot be converted to bool? */ } else if (has_set_exists < ZEND_PROPERTY_NOT_EMPTY) { ZEND_ASSERT(has_set_exists == ZEND_PROPERTY_ISSET); ZVAL_DEREF(value); @@ -1708,6 +1713,7 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has zend_std_call_issetter(zobj, name, &rv); result = zend_is_true(&rv); zval_ptr_dtor(&rv); + /* TODO: need to do something if retval is an object which cannot be converted to bool? */ if (has_set_exists == ZEND_PROPERTY_NOT_EMPTY && result) { if (EXPECTED(!EG(exception)) && zobj->ce->__get && !((*guard) & IN_GET)) { (*guard) |= IN_GET; @@ -1715,6 +1721,7 @@ ZEND_API int zend_std_has_property(zend_object *zobj, zend_string *name, int has (*guard) &= ~IN_GET; result = i_zend_is_true(&rv); zval_ptr_dtor(&rv); + /* TODO: need to do something if retval is an object which cannot be converted to bool? */ } else { result = 0; } diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 1db18168564a3..206b86dc380c8 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1423,7 +1423,7 @@ ZEND_API zend_result ZEND_FASTCALL mod_function(zval *result, zval *op1, zval *o ZEND_API zend_result ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, zval *op2) /* {{{ */ { - int op1_val, op2_val; + bool op1_val, op2_val; do { if (Z_TYPE_P(op1) == IS_FALSE) { @@ -1443,6 +1443,10 @@ ZEND_API zend_result ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, } ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BOOL_XOR); op1_val = zval_is_true(op1); + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(result); + return FAILURE; + } } } while (0); do { @@ -1463,6 +1467,10 @@ ZEND_API zend_result ZEND_FASTCALL boolean_xor_function(zval *result, zval *op1, } ZEND_TRY_BINARY_OP2_OBJECT_OPERATION(ZEND_BOOL_XOR); op2_val = zval_is_true(op2); + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(result); + return FAILURE; + } } } while (0); @@ -1478,6 +1486,7 @@ ZEND_API zend_result ZEND_FASTCALL boolean_not_function(zval *result, zval *op1) } else if (EXPECTED(Z_TYPE_P(op1) == IS_TRUE)) { ZVAL_FALSE(result); } else { + bool not; if (Z_ISREF_P(op1)) { op1 = Z_REFVAL_P(op1); if (Z_TYPE_P(op1) < IS_TRUE) { @@ -1490,7 +1499,12 @@ ZEND_API zend_result ZEND_FASTCALL boolean_not_function(zval *result, zval *op1) } ZEND_TRY_UNARY_OBJECT_OPERATION(ZEND_BOOL_NOT); - ZVAL_BOOL(result, !zval_is_true(op1)); + not = !zval_is_true(op1); + if (UNEXPECTED(EG(exception))) { + ZVAL_UNDEF(result); + return FAILURE; + } + ZVAL_BOOL(result, not); } return SUCCESS; } @@ -2214,13 +2228,29 @@ ZEND_API int ZEND_FASTCALL zend_compare(zval *op1, zval *op2) /* {{{ */ if (!converted) { if (Z_TYPE_P(op1) < IS_TRUE) { - return zval_is_true(op2) ? -1 : 0; + bool is_true = zval_is_true(op2); + if (UNEXPECTED(EG(exception))) { + return 1; + } + return is_true ? -1 : 0; } else if (Z_TYPE_P(op1) == IS_TRUE) { - return zval_is_true(op2) ? 0 : 1; + bool is_true = zval_is_true(op2); + if (UNEXPECTED(EG(exception))) { + return 1; + } + return is_true ? 0 : 1; } else if (Z_TYPE_P(op2) < IS_TRUE) { - return zval_is_true(op1) ? 1 : 0; + bool is_true = zval_is_true(op1); + if (UNEXPECTED(EG(exception))) { + return 1; + } + return is_true ? 1 : 0; } else if (Z_TYPE_P(op2) == IS_TRUE) { - return zval_is_true(op1) ? 0 : -1; + bool is_true = zval_is_true(op1); + if (UNEXPECTED(EG(exception))) { + return 1; + } + return is_true ? 0 : -1; } else { op1 = _zendi_convert_scalar_to_number_silent(op1, &op1_copy); op2 = _zendi_convert_scalar_to_number_silent(op2, &op2_copy); @@ -2594,6 +2624,7 @@ ZEND_API zend_result ZEND_FASTCALL decrement_function(zval *op1) /* {{{ */ } /* }}} */ +/* TODO make JIT compatible with a bool return */ ZEND_API int ZEND_FASTCALL zend_is_true(zval *op) /* {{{ */ { return (int) i_zend_is_true(op); @@ -2607,7 +2638,7 @@ ZEND_API bool ZEND_FASTCALL zend_object_is_true(zval *op) /* {{{ */ if (zobj->handlers->cast_object(zobj, &tmp, _IS_BOOL) == SUCCESS) { return Z_TYPE(tmp) == IS_TRUE; } - zend_error(E_RECOVERABLE_ERROR, "Object of class %s could not be converted to bool", ZSTR_VAL(zobj->ce->name)); + zend_type_error("Object of class %s could not be converted to bool", ZSTR_VAL(zobj->ce->name)); return false; } /* }}} */ diff --git a/ext/bz2/bz2_filter.c b/ext/bz2/bz2_filter.c index 4c573638366f1..37c8925f24329 100644 --- a/ext/bz2/bz2_filter.c +++ b/ext/bz2/bz2_filter.c @@ -339,6 +339,10 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi if (Z_TYPE_P(filterparams) == IS_ARRAY || Z_TYPE_P(filterparams) == IS_OBJECT) { if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), "concatenated", sizeof("concatenated")-1))) { data->expect_concatenated = zend_is_true(tmpzval); + if (EG(exception)) { + status = BZ_DATA_ERROR; + // TODO Goto cleanup? + } tmpzval = NULL; } @@ -349,6 +353,10 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi if (tmpzval) { data->small_footprint = zend_is_true(tmpzval); + if (EG(exception)) { + status = BZ_DATA_ERROR; + // TODO Goto cleanup? + } } } diff --git a/ext/curl/interface.c b/ext/curl/interface.c index b0e2b6170c068..a966a5f820956 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -2451,6 +2451,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i break; case CURLOPT_SAFE_UPLOAD: if (!zend_is_true(zvalue)) { + /* Handles case where zvalue is an object which cannot be cast to bool at the same time */ zend_value_error("%s(): Disabling safe uploads is no longer supported", get_active_function_name()); return FAILURE; } @@ -2784,6 +2785,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i case CURLOPT_FOLLOWLOCATION: lval = zend_is_true(zvalue); + /* If zvalue is an object which cannot be cast to bool */ + if (EG(exception)) { + error = CURLE_UNKNOWN_OPTION; + break; + } error = curl_easy_setopt(ch->cp, option, lval); break; @@ -2841,6 +2847,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i if (zend_is_true(zvalue)) { ch->handlers.write->method = PHP_CURL_RETURN; } else { + /* If zvalue is an object which cannot be cast to bool */ + if (EG(exception)) { + error = CURLE_UNKNOWN_OPTION; + break; + } ch->handlers.write->method = PHP_CURL_STDOUT; } break; @@ -2903,6 +2914,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch); curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1); } else { + /* If zvalue is an object which cannot be cast to bool */ + if (EG(exception)) { + error = CURLE_UNKNOWN_OPTION; + break; + } curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL); curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL); curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0); diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 116a2135258f3..14020175787f6 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1588,6 +1588,7 @@ static int date_interval_has_property(zend_object *object, zend_string *name, in if (type == 2) { retval = 1; } else if (type == 1) { + /* TODO: Check if special handling needs to be done when prop is an object which cannot be converted to bool */ retval = zend_is_true(prop); } else if (type == 0) { retval = (Z_TYPE_P(prop) != IS_NULL); diff --git a/ext/dom/document.c b/ext/dom/document.c index 85879790a75f3..71f5560a70253 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -284,6 +284,9 @@ int dom_document_strict_error_checking_write(dom_object *obj, zval *newval) if (obj->document) { dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document); doc_prop->stricterror = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } } return SUCCESS; @@ -310,6 +313,9 @@ int dom_document_format_output_write(dom_object *obj, zval *newval) if (obj->document) { dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document); doc_prop->formatoutput = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } } return SUCCESS; @@ -335,6 +341,9 @@ int dom_document_validate_on_parse_write(dom_object *obj, zval *newval) if (obj->document) { dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document); doc_prop->validateonparse = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } } return SUCCESS; @@ -360,6 +369,9 @@ int dom_document_resolve_externals_write(dom_object *obj, zval *newval) if (obj->document) { dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document); doc_prop->resolveexternals = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } } return SUCCESS; @@ -385,6 +397,9 @@ int dom_document_preserve_whitespace_write(dom_object *obj, zval *newval) if (obj->document) { dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document); doc_prop->preservewhitespace = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } } return SUCCESS; @@ -410,6 +425,9 @@ int dom_document_recover_write(dom_object *obj, zval *newval) if (obj->document) { dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document); doc_prop->recover = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } } return SUCCESS; @@ -435,6 +453,9 @@ int dom_document_substitue_entities_write(dom_object *obj, zval *newval) if (obj->document) { dom_doc_propsptr doc_prop = dom_get_doc_props(obj->document); doc_prop->substituteentities = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } } return SUCCESS; diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index ccf74d23d0ed8..516ed3a71be1d 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -370,6 +370,7 @@ static int dom_property_exists(zend_object *object, zend_string *name, int check retval = 1; } else if (hnd->read_func(obj, &tmp) == SUCCESS) { if (check_empty == 1) { + /* TODO Check can tmp be an object */ retval = zend_is_true(&tmp); } else if (check_empty == 0) { retval = (Z_TYPE(tmp) != IS_NULL); diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index 876d8b00dae0e..c8b5710d30bc1 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -280,6 +280,9 @@ int dom_xpath_register_node_ns_read(dom_object *obj, zval *retval) int dom_xpath_register_node_ns_write(dom_object *obj, zval *newval) { php_xpath_obj_from_dom_obj(obj)->register_node_ns = zend_is_true(newval); + if (EG(exception)) { + return FAILURE; + } return SUCCESS; } diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 4e30ec577144c..9415f610df866 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -734,6 +734,11 @@ static zend_always_inline int zend_ffi_zval_to_cdata(void *ptr, zend_ffi_type *t break; case ZEND_FFI_TYPE_BOOL: *(uint8_t*)ptr = zend_is_true(value); + /* If value is an object which cannot be converted to bool */ + if (EG(exception)) { + zend_ffi_assign_incompatible(value, type); + return FAILURE; + } break; case ZEND_FFI_TYPE_CHAR: str = zval_get_tmp_string(value, &tmp_str); @@ -2544,6 +2549,11 @@ static int zend_ffi_pass_arg(zval *arg, zend_ffi_type *type, ffi_type **pass_typ case ZEND_FFI_TYPE_BOOL: *pass_type = &ffi_type_uint8; *(uint8_t*)arg_values[n] = zend_is_true(arg); + /* If value is an object which cannot be converted to bool */ + if (EG(exception)) { + zend_ffi_assign_incompatible(arg, type); + return FAILURE; + } break; case ZEND_FFI_TYPE_CHAR: str = zval_get_tmp_string(arg, &tmp_str); diff --git a/ext/gmp/tests/cast.phpt b/ext/gmp/tests/cast.phpt index 661a0159b94e1..593b07bea6dc6 100644 --- a/ext/gmp/tests/cast.phpt +++ b/ext/gmp/tests/cast.phpt @@ -10,13 +10,15 @@ echo $n, "\n"; var_dump((string) $n); var_dump((int) $n); var_dump((float) $n); -var_dump((bool) $n); - +try { + var_dump((bool) $n); +} catch (\TypeError $e) { + echo $e->getMessage() . \PHP_EOL; +} ?> ---EXPECTF-- +--EXPECT-- 42 string(2) "42" int(42) float(42) - -Recoverable fatal error: Object of class GMP could not be converted to bool in %s on line %d +Object of class GMP could not be converted to bool diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 13a3c7b6b8f5f..67db066f4766b 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -407,6 +407,10 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "iscritical", sizeof("iscritical") - 1)) != NULL) { control_iscritical = zend_is_true(val); + /* If val is an object which cannot be converted to object */ + if (EG(exception)) { + return -1; + } } else { control_iscritical = 0; } @@ -592,6 +596,11 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "reverse", sizeof("reverse") - 1)) != NULL) { sort_keys[i]->reverseOrder = zend_is_true(tmp); + /* If val is an object which cannot be converted to object */ + if (EG(exception)) { + rc = -1; + goto failure; + } } else { sort_keys[i]->reverseOrder = 0; } @@ -3396,6 +3405,10 @@ PHP_FUNCTION(ldap_set_option) { void *val; val = zend_is_true(newval) ? LDAP_OPT_ON : LDAP_OPT_OFF; + /* If val is an object which cannot be converted to object */ + if (EG(exception)) { + RETURN_THROWS(); + } if (ldap_set_option(ldap, option, val)) { RETURN_FALSE; } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 771126f644215..b6b87b09d1b33 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -8201,6 +8201,7 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, uint32_ } if (Z_MODE(op1_addr) == IS_CONST_ZVAL) { + /* zend_is_true() cannot fail as op1 cannot be an object */ if (zend_is_true(Z_ZV(op1_addr))) { /* Always TRUE */ if (set_bool) { diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 0a9491476b9b2..0de5c48ac5177 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -305,6 +305,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ GET_VER_OPT("allow_self_signed") && zend_is_true(val) ) { + /* TODO Check if stream context value can be an object */ ret = 1; } @@ -510,6 +511,7 @@ static int php_openssl_apply_peer_verification_policy(SSL *ssl, X509 *peer, php_ php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract; + /* TODO Check if stream context value can be an object */ must_verify_peer = GET_VER_OPT("verify_peer") ? zend_is_true(val) : sslsock->is_client; diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index 4c20700379731..633a0dc129cbc 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -259,6 +259,10 @@ safe: switch (param_type) { case PDO_PARAM_BOOL: plc->quoted = zend_is_true(parameter) ? ZSTR_CHAR('1') : ZSTR_CHAR('0'); + // TODO Can an exception occur here? + if (EG(exception)) { + goto clean_up; + } break; case PDO_PARAM_INT: diff --git a/ext/pdo/tests/type_error_cannot_convert_to_bool.phpt b/ext/pdo/tests/type_error_cannot_convert_to_bool.phpt new file mode 100644 index 0000000000000..34fed26095aeb --- /dev/null +++ b/ext/pdo/tests/type_error_cannot_convert_to_bool.phpt @@ -0,0 +1,38 @@ +--TEST-- +PDO Common: TypeError when binding an object as a boolean which cannot be converted +--EXTENSIONS-- +pdo +gmp +--SKIPIF-- + +--FILE-- +exec('CREATE TABLE test(id int NOT NULL PRIMARY KEY, val boolean)'); +$db->exec('INSERT INTO test VALUES(1, TRUE)'); +$db->exec('INSERT INTO test VALUES(2, FALSE)'); + +$gmp = gmp_init('20', 10); + +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); +$s = $db->prepare('SELECT id FROM test WHERE val = :bval'); +$s->bindValue(':bval', $gmp, PDO::PARAM_BOOL); + +try { + $s->execute(); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} +?> +==DONE== +--EXPECT-- +Object of class GMP could not be converted to bool +==DONE== diff --git a/ext/pdo_odbc/odbc_stmt.c b/ext/pdo_odbc/odbc_stmt.c index d059e62a2771c..721226c265858 100644 --- a/ext/pdo_odbc/odbc_stmt.c +++ b/ext/pdo_odbc/odbc_stmt.c @@ -773,6 +773,9 @@ static int odbc_stmt_set_param(pdo_stmt_t *stmt, zend_long attr, zval *val) case PDO_ODBC_ATTR_ASSUME_UTF8: S->assume_utf8 = zval_is_true(val); + if (EG(exception)) { + return -1; + } return 0; default: strcpy(S->einfo.last_err_msg, "Unknown Attribute"); diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c index ae4640c655e43..081176d889f23 100644 --- a/ext/pdo_pgsql/pgsql_statement.c +++ b/ext/pdo_pgsql/pgsql_statement.c @@ -401,8 +401,11 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data * if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_BOOL && ((param->param_type & PDO_PARAM_INPUT_OUTPUT) != PDO_PARAM_INPUT_OUTPUT)) { const char *s = zend_is_true(¶m->parameter) ? "t" : "f"; - param->param_type = PDO_PARAM_STR; zval_ptr_dtor(¶m->parameter); + if (EG(exception)) { + return 0; + } + param->param_type = PDO_PARAM_STR; ZVAL_STRINGL(¶m->parameter, s, 1); } } diff --git a/ext/readline/readline.c b/ext/readline/readline.c index 544258eeca621..4c678f7905268 100644 --- a/ext/readline/readline.c +++ b/ext/readline/readline.c @@ -219,6 +219,10 @@ PHP_FUNCTION(readline_info) oldval = rl_completion_suppress_append; if (value) { rl_completion_suppress_append = zend_is_true(value); + /* If value is an object which cannot be converted to bool */ + if (EG(exception)) { + RETURN_THROWS(); + } } RETVAL_BOOL(oldval); } else if (zend_string_equals_literal_ci(what, "completion_append_character")) { diff --git a/ext/session/session.c b/ext/session/session.c index c096e809c17de..a00cfe8bdfd98 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1743,10 +1743,18 @@ PHP_FUNCTION(session_set_cookie_params) found++; } else if (zend_string_equals_literal_ci(key, "secure")) { secure = zval_is_true(value); + /* Exception during string conversion */ + if (EG(exception)) { + goto cleanup; + } secure_null = 0; found++; } else if (zend_string_equals_literal_ci(key, "httponly")) { httponly = zval_is_true(value); + /* Exception during string conversion */ + if (EG(exception)) { + goto cleanup; + } httponly_null = 0; found++; } else if (zend_string_equals_literal_ci(key, "samesite")) { diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index feb8e583c13bb..8d8cebb03bc8b 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -1130,6 +1130,7 @@ static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNode xmlAddChild(parent, ret); FIND_ZVAL_NULL(data, ret, style); + /* TODO: Check if when data is an object which cannnot be converted to bool special handling is needed? */ if (zend_is_true(data)) { xmlNodeSetContent(ret, BAD_CAST("true")); } else { diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 6d96b723aecf8..56095fa2bdd5c 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -586,6 +586,7 @@ static int spl_array_has_dimension_ex(bool check_inherited, zend_object *object, if (check_inherited && intern->fptr_offset_has) { zend_call_method_with_1_params(object, object->ce, &intern->fptr_offset_has, "offsetExists", &rv, offset); + /* Return value must be a bool therefore zend_is_true() cannot fail */ if (!zend_is_true(&rv)) { zval_ptr_dtor(&rv); return 0; @@ -638,6 +639,7 @@ static int spl_array_has_dimension_ex(bool check_inherited, zend_object *object, } /* empty() check the value is not falsy, isset() only check it is not null */ + /* Do not check that a TypeError is emitted by zend_is_true() as we're already returning */ return check_empty ? zend_is_true(value) : Z_TYPE_P(value) != IS_NULL; } /* }}} */ diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index a3f6b21405e6b..1f5de63e621e7 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -851,6 +851,10 @@ PHP_METHOD(DirectoryIterator, seek) zend_call_method_with_0_params(Z_OBJ_P(ZEND_THIS), Z_OBJCE_P(ZEND_THIS), &intern->u.dir.func_valid, "valid", &retval); valid = zend_is_true(&retval); zval_ptr_dtor(&retval); + /* Is this block needed as we are calling a known function */ + if (EG(exception)) { + RETURN_THROWS(); + } if (!valid) { zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position " ZEND_LONG_FMT " is out of range", pos); RETURN_THROWS(); diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 06f885f182214..ebce39a2659b2 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -486,6 +486,7 @@ static bool spl_fixedarray_object_has_dimension_helper(spl_fixedarray_object *in } if (check_empty) { + /* Do not check that a TypeError is emitted by zend_is_true() as we're already returning */ return zend_is_true(&intern->array.elements[index]); } @@ -505,6 +506,7 @@ static int spl_fixedarray_object_has_dimension(zend_object *object, zval *offset zend_call_method_with_1_params(object, intern->std.ce, &intern->methods->fptr_offset_has, "offsetExists", &rv, offset); result = zend_is_true(&rv); zval_ptr_dtor(&rv); + /* Need to do something if rv is an object which can't be converted to bool? */ return result; } diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 4425d58a5990b..26bf6f06686df 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -276,6 +276,9 @@ static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zv if (Z_TYPE(retval) != IS_UNDEF) { has_children = zend_is_true(&retval); zval_ptr_dtor(&retval); + if (EG(exception)) { + return; + } if (has_children) { if (object->max_depth == -1 || object->max_depth > object->level) { switch (object->mode) { @@ -2328,6 +2331,7 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern) return; } } else { + /* retval should be a bool therefore zend_is_true() cannot fail */ if (zend_is_true(&retval)) { zend_call_method_with_0_params(Z_OBJ(intern->inner.zobject), intern->inner.ce, NULL, "getchildren", &zchildren); if (EG(exception)) { @@ -3164,6 +3168,7 @@ static int spl_iterator_func_apply(zend_object_iterator *iter, void *puser) /* { apply_info->count++; zend_fcall_info_call(&apply_info->fci, &apply_info->fcc, &retval, NULL); + /* No special handling in case retval is an object */ result = zend_is_true(&retval) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_STOP; zval_ptr_dtor(&retval); return result; diff --git a/ext/standard/array.c b/ext/standard/array.c index c3227386b6bd9..0ef15f62052e8 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -5879,6 +5879,9 @@ PHP_FUNCTION(array_filter) } retval_true = zend_is_true(&retval); zval_ptr_dtor(&retval); + if (EG(exception)) { + RETURN_THROWS(); + } if (!retval_true) { continue; } @@ -5890,6 +5893,9 @@ PHP_FUNCTION(array_filter) return; } } else if (!zend_is_true(operand)) { + if (EG(exception)) { + RETURN_THROWS(); + } continue; } diff --git a/ext/standard/assert.c b/ext/standard/assert.c index 1c5108b94e5b2..46b9d0f3beab9 100644 --- a/ext/standard/assert.c +++ b/ext/standard/assert.c @@ -148,6 +148,9 @@ PHP_FUNCTION(assert) ZEND_PARSE_PARAMETERS_END(); if (zend_is_true(assertion)) { + if (EG(exception)) { + RETURN_THROWS(); + } RETURN_TRUE; } diff --git a/ext/standard/filters.c b/ext/standard/filters.c index b390ac7b0a212..c371adb8368dc 100644 --- a/ext/standard/filters.c +++ b/ext/standard/filters.c @@ -1125,6 +1125,9 @@ static php_conv_err_t php_conv_get_bool_prop_ex(const HashTable *ht, int *pretva zval *tmpval = zend_hash_str_find((HashTable *)ht, field_name, field_name_len-1); if (tmpval != NULL) { *pretval = zend_is_true(tmpval); + if (EG(exception)) { + return PHP_CONV_ERR_NOT_FOUND; + } return PHP_CONV_ERR_SUCCESS; } else { *pretval = 0; diff --git a/ext/standard/head.c b/ext/standard/head.c index ab64fecf381aa..bdc08391cee81 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -210,9 +210,16 @@ static zend_result php_head_parse_cookie_options_array(HashTable *options, zend_ } else if (zend_string_equals_literal_ci(key, "domain")) { *domain = zval_get_string(value); } else if (zend_string_equals_literal_ci(key, "secure")) { + /* Explicitly disallow object? */ *secure = zval_is_true(value); + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } } else if (zend_string_equals_literal_ci(key, "httponly")) { *httponly = zval_is_true(value); + if (UNEXPECTED(EG(exception))) { + return FAILURE; + } } else if (zend_string_equals_literal_ci(key, "samesite")) { *samesite = zval_get_string(value); } else { diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index 761d46b2c90c0..7e4944fd9eb25 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -382,6 +382,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, /* Should we send the entire path in the request line, default to no. */ if (!request_fulluri && context && (tmpzval = php_stream_context_get_option(context, "http", "request_fulluri")) != NULL) { + /* TODO Check if stream context value can be an object */ request_fulluri = zend_is_true(tmpzval); } @@ -772,7 +773,11 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, if (!strncasecmp(http_header_line, "Location:", sizeof("Location:")-1)) { if (context && (tmpzval = php_stream_context_get_option(context, "http", "follow_location")) != NULL) { + /* Can tmpzval be an object? */ follow_location = zval_is_true(tmpzval); + if (UNEXPECTED(EG(exception))) { + goto out; + } } else if (!((response_code >= 300 && response_code < 304) || 307 == response_code || 308 == response_code)) { /* we shouldn't redirect automatically diff --git a/ext/standard/tests/array/array_filter_variation11.phpt b/ext/standard/tests/array/array_filter_variation11.phpt new file mode 100644 index 0000000000000..ef85aab745825 --- /dev/null +++ b/ext/standard/tests/array/array_filter_variation11.phpt @@ -0,0 +1,34 @@ +--TEST-- +Test array_filter() function : value cannot be converted to bool +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), \PHP_EOL; +} + +$input = [gmp_init(5), gmp_init(25)]; + +try { + var_dump( array_filter($input) ); +} catch (\TypeError $e) { + echo $e->getMessage(), \PHP_EOL; +} + +echo "Done" +?> +--EXPECT-- +Object of class GMP could not be converted to bool +Object of class GMP could not be converted to bool +Done diff --git a/ext/standard/tests/general_functions/boolval_unconvertable_value.phpt b/ext/standard/tests/general_functions/boolval_unconvertable_value.phpt new file mode 100644 index 0000000000000..dbefc054d560d --- /dev/null +++ b/ext/standard/tests/general_functions/boolval_unconvertable_value.phpt @@ -0,0 +1,14 @@ +--TEST-- +Testing boolval() +--EXTENSIONS-- +gmp +--FILE-- +getMessage(), \PHP_EOL; +} +?> +--EXPECT-- +Object of class GMP could not be converted to bool diff --git a/ext/standard/var.c b/ext/standard/var.c index 2c5b4b0cf6e35..077aa14f238cc 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -1352,6 +1352,7 @@ PHPAPI void php_unserialize_with_options(zval *return_value, const char *buf, co goto cleanup; } + /* zend_is_true() cannot fail as it is or a boolean or an array */ if(classes && (Z_TYPE_P(classes) == IS_ARRAY || !zend_is_true(classes))) { ALLOC_HASHTABLE(class_hash); zend_hash_init(class_hash, (Z_TYPE_P(classes) == IS_ARRAY)?zend_hash_num_elements(Z_ARRVAL_P(classes)):0, NULL, NULL, 0); diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index cf8506fa389a2..d8f6541874ad8 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -955,6 +955,7 @@ static int php_zip_has_property(zend_object *object, zend_string *name, int type } else if ((prop = php_zip_property_reader(obj, hnd, &tmp)) != NULL) { if (type == 1) { retval = zend_is_true(&tmp); + /* TODO Check if need to do special handling in case tmp is an object which cannot be converted to bool? */ } else if (type == 0) { retval = (Z_TYPE(tmp) != IS_NULL); } diff --git a/main/streams/userspace.c b/main/streams/userspace.c index d134188c0e960..90d7bd70b74f5 100644 --- a/main/streams/userspace.c +++ b/main/streams/userspace.c @@ -360,6 +360,7 @@ static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, const char * zend_bailout(); } zend_end_try(); + /* TODO Check can zretval be an object? */ if (call_result == SUCCESS && Z_TYPE(zretval) != IS_UNDEF && zval_is_true(&zretval)) { /* the stream is now open! */ stream = php_stream_alloc_rel(&php_stream_userspace_ops, us, 0, mode); @@ -434,6 +435,7 @@ static php_stream *user_wrapper_opendir(php_stream_wrapper *wrapper, const char &zretval, 2, args); + /* TODO Check can zretval be an object? */ if (call_result == SUCCESS && Z_TYPE(zretval) != IS_UNDEF && zval_is_true(&zretval)) { /* the stream is now open! */ stream = php_stream_alloc_rel(&php_stream_userspace_dir_ops, us, 0, mode); @@ -679,6 +681,8 @@ static ssize_t php_userstreamop_read(php_stream *stream, char *buf, size_t count return -1; } + /* TODO Check retval is an object for zval_is_true() */ + if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) { stream->eof = 1; } else if (call_result == FAILURE) { @@ -738,6 +742,7 @@ static int php_userstreamop_flush(php_stream *stream) &retval, 0, NULL); + /* TODO Check retval is an object for zval_is_true() */ if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) call_result = 0; else @@ -783,6 +788,7 @@ static int php_userstreamop_seek(php_stream *stream, zend_off_t offset, int when return -1; } else if (call_result == SUCCESS && Z_TYPE(retval) != IS_UNDEF && zval_is_true(&retval)) { + /* TODO Check retval is an object for zval_is_true() */ ret = 0; } else { ret = -1; @@ -1052,6 +1058,9 @@ static int php_userstreamop_set_option(php_stream *stream, int option, int value ZSTR_VAL(us->wrapper->ce->name)); ret = PHP_STREAM_OPTION_RETURN_ERR; } else if (zend_is_true(&retval)) { + if (EG(exception)) { + ret = PHP_STREAM_OPTION_RETURN_ERR; + } ret = PHP_STREAM_OPTION_RETURN_OK; } else { ret = PHP_STREAM_OPTION_RETURN_ERR; @@ -1491,6 +1500,7 @@ static int php_userstreamop_cast(php_stream *stream, int castas, void **retptr) break; } if (!zend_is_true(&retval)) { + /* return is already FAILURE */ break; } php_stream_from_zval_no_verify(intstream, &retval); diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 10d584fa42415..ba3c4e04359e5 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -664,6 +664,9 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * sockopts |= STREAM_SOCKOP_IPV6_V6ONLY; sockopts |= STREAM_SOCKOP_IPV6_V6ONLY_ENABLED * zend_is_true(tmpzval); } + if (EG(exception)) { + return -1; + } #endif #ifdef SO_REUSEPORT @@ -673,6 +676,9 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * ) { sockopts |= STREAM_SOCKOP_SO_REUSEPORT; } + if (EG(exception)) { + return -1; + } #endif #ifdef SO_BROADCAST @@ -683,6 +689,9 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * ) { sockopts |= STREAM_SOCKOP_SO_BROADCAST; } + if (EG(exception)) { + return -1; + } #endif sock->socket = php_network_bind_socket_to_local_addr(host, portno, @@ -761,6 +770,9 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ ) { sockopts |= STREAM_SOCKOP_SO_BROADCAST; } + if (EG(exception)) { + return -1; + } #endif if (stream->ops != &php_stream_udp_socket_ops /* TCP_NODELAY is only applicable for TCP */ @@ -774,6 +786,10 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ ) { sockopts |= STREAM_SOCKOP_TCP_NODELAY; } + /* TODO Need to do cleanup? */ + if (EG(exception)) { + return -1; + } /* Note: the test here for php_stream_udp_socket_ops is important, because we * want the default to be TCP sockets so that the openssl extension can @@ -826,6 +842,9 @@ static inline int php_tcp_sockop_accept(php_stream *stream, php_netstream_data_t zend_is_true(tmpzval)) { nodelay = 1; } + if (EG(exception)) { + return -1; + } clisock = php_network_accept_incoming(sock->socket, xparam->want_textaddr ? &xparam->outputs.textaddr : NULL, diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 4503e85d92849..7d2e611464bed 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -511,11 +511,19 @@ PHP_FUNCTION(phpdbg_get_executable) if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("functions")))) { by_function = zend_is_true(option_buffer); + /* If option_buffer is an object which cannot be cast to bool */ + if (EG(exception)) { + RETURN_THROWS(); + } } if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("opcodes")))) { if (by_function) { by_opcode = zend_is_true(option_buffer); + /* If option_buffer is an object which cannot be cast to bool */ + if (EG(exception)) { + RETURN_THROWS(); + } } } @@ -616,11 +624,19 @@ PHP_FUNCTION(phpdbg_end_oplog) if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("functions")))) { by_function = zend_is_true(option_buffer); + /* If option_buffer is an object which cannot be cast to bool */ + if (EG(exception)) { + RETURN_THROWS(); + } } if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("opcodes")))) { if (by_function) { by_opcode = zend_is_true(option_buffer); + /* If option_buffer is an object which cannot be cast to bool */ + if (EG(exception)) { + RETURN_THROWS(); + } } } diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index ae35c740a594f..93ac6c1a53305 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -1120,6 +1120,10 @@ static inline phpdbg_breakbase_t *phpdbg_find_conditional_breakpoint(zend_execut PHPDBG_G(flags) |= PHPDBG_IN_COND_BP; zend_execute(bp->ops, &retval); if (zend_is_true(&retval)) { + /* If retval is an object which cannot be cast to bool */ + if (EG(exception)) { + breakpoint = FAILURE; + } breakpoint = SUCCESS; } } zend_end_try();