From: Bob Weinand Date: Wed, 17 Feb 2016 19:26:47 +0000 (+0100) Subject: Fix crash when advancing inside an internal function X-Git-Tag: php-7.0.5RC1~109 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=055b4112188cccdc250790ab063479d2922f5fda;p=php Fix crash when advancing inside an internal function This just happened in the "double ctrl+c" mode, when we halted inside an internal function; there was some code assuming a proper op_array --- diff --git a/NEWS b/NEWS index 60c75747a3..9d3ddf491e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2016 PHP 7.0.5 +- phpdbg: + . Fixed crash when advancing (except step) inside an internal function. (Bob) ?? ??? 2016 PHP 7.0.4 diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index eac67d4ac7..5436bda5db 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -563,12 +563,14 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break) /* { } else { zend_execute_data *execute_data = EG(current_execute_data); do { - zend_op_array *op_array = &execute_data->func->op_array; - if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) { - if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) { - return SUCCESS; - } else { - return 2; + if (ZEND_USER_CODE(execute_data->func->common.type)) { + zend_op_array *op_array = &execute_data->func->op_array; + if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) { + if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) { + return SUCCESS; + } else { + return 2; + } } } } while ((execute_data = execute_data->prev_execute_data) != NULL); diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c index abfad0219a..00209cb239 100644 --- a/sapi/phpdbg/phpdbg_print.c +++ b/sapi/phpdbg/phpdbg_print.c @@ -42,7 +42,7 @@ const phpdbg_command_t phpdbg_print_commands[] = { PHPDBG_PRINT(opline) /* {{{ */ { if (PHPDBG_G(in_execution) && EG(current_execute_data)) { - phpdbg_print_opline(EG(current_execute_data), 1); + phpdbg_print_opline(phpdbg_user_execute_data(EG(current_execute_data)), 1); } else { phpdbg_error("inactive", "type=\"execution\"", "Not Executing!"); } @@ -124,7 +124,7 @@ return SUCCESS; PHPDBG_PRINT(stack) /* {{{ */ { if (PHPDBG_G(in_execution) && EG(current_execute_data)) { - zend_op_array *ops = &EG(current_execute_data)->func->op_array; + zend_op_array *ops = &phpdbg_user_execute_data(EG(current_execute_data))->func->op_array; if (ops->function_name) { if (ops->scope) { phpdbg_notice("printinfo", "method=\"%s::%s\" num=\"%d\"", "Stack in %s::%s() (%d ops)", ZSTR_VAL(ops->scope->name), ZSTR_VAL(ops->function_name), ops->last); diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 0314442daa..558ca469b5 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -518,13 +518,14 @@ PHPDBG_COMMAND(continue) /* {{{ */ } /* }}} */ int phpdbg_skip_line_helper() /* {{{ */ { - const zend_op_array *op_array = &EG(current_execute_data)->func->op_array; + zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data)); + const zend_op_array *op_array = &ex->func->op_array; const zend_op *opline = op_array->opcodes; PHPDBG_G(flags) |= PHPDBG_IN_UNTIL; - PHPDBG_G(seek_ex) = EG(current_execute_data); + PHPDBG_G(seek_ex) = ex; do { - if (opline->lineno != EG(current_execute_data)->opline->lineno + if (opline->lineno != ex->opline->lineno || opline->opcode == ZEND_RETURN || opline->opcode == ZEND_FAST_RET || opline->opcode == ZEND_GENERATOR_RETURN @@ -562,10 +563,11 @@ PHPDBG_COMMAND(next) /* {{{ */ } /* }}} */ static void phpdbg_seek_to_end(void) /* {{{ */ { - const zend_op_array *op_array = &EG(current_execute_data)->func->op_array; + zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data)); + const zend_op_array *op_array = &ex->func->op_array; const zend_op *opline = op_array->opcodes; - PHPDBG_G(seek_ex) = EG(current_execute_data); + PHPDBG_G(seek_ex) = ex; do { switch (opline->opcode) { case ZEND_RETURN: @@ -588,7 +590,7 @@ PHPDBG_COMMAND(finish) /* {{{ */ } phpdbg_seek_to_end(); - if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) EG(current_execute_data)->opline)) { + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { zend_hash_clean(&PHPDBG_G(seek)); } else { PHPDBG_G(flags) |= PHPDBG_IN_FINISH; @@ -605,7 +607,7 @@ PHPDBG_COMMAND(leave) /* {{{ */ } phpdbg_seek_to_end(); - if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) EG(current_execute_data)->opline)) { + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { zend_hash_clean(&PHPDBG_G(seek)); phpdbg_notice("leave", "type=\"end\"", "Already at the end of the function"); return SUCCESS; diff --git a/sapi/phpdbg/phpdbg_utils.h b/sapi/phpdbg/phpdbg_utils.h index 2bd4f35d71..4ba756139b 100644 --- a/sapi/phpdbg/phpdbg_utils.h +++ b/sapi/phpdbg/phpdbg_utils.h @@ -99,6 +99,14 @@ char *phpdbg_short_zval_print(zval *zv, int maxlen); PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *ex, zend_object *exception); +static zend_always_inline zend_execute_data *phpdbg_user_execute_data(zend_execute_data *ex) { + while (!ex->func || !ZEND_USER_CODE(ex->func->common.type)) { + ex = ex->prev_execute_data; + ZEND_ASSERT(ex); + } + return ex; +} + #ifdef ZTS #define PHPDBG_OUTPUT_BACKUP_DEFINES() \ zend_output_globals *output_globals_ptr; \