]> granicus.if.org Git - php/commitdiff
Fix crash when advancing inside an internal function
authorBob Weinand <bobwei9@hotmail.com>
Wed, 17 Feb 2016 19:26:47 +0000 (20:26 +0100)
committerBob Weinand <bobwei9@hotmail.com>
Wed, 17 Feb 2016 19:27:46 +0000 (20:27 +0100)
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

NEWS
sapi/phpdbg/phpdbg_bp.c
sapi/phpdbg/phpdbg_print.c
sapi/phpdbg/phpdbg_prompt.c
sapi/phpdbg/phpdbg_utils.h

diff --git a/NEWS b/NEWS
index 60c75747a36f0347188c19038e032e94e391e5a8..9d3ddf491e77848a9a3dc946137726a9544150c4 100644 (file)
--- 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
 
index eac67d4ac7251a8d3f8a3062df9512c85bfbd688..5436bda5db62a89b8965a7c29da3f2aacece99e8 100644 (file)
@@ -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);
index abfad0219af7e03955cc53413cfa06f830012a4c..00209cb239f621d94df24d1d5edafde011ec0712 100644 (file)
@@ -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);
index 0314442daa891d583e2e2c3b49edb9a112ff1ab0..558ca469b57af3ce32114218a3fd086544022ea9 100644 (file)
@@ -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;
index 2bd4f35d71d68d0098a98c4ec89fd0d44ec0faa4..4ba756139bcfe0868938e2340a67c1f5fde1ebfc 100644 (file)
@@ -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; \