]> granicus.if.org Git - php/commitdiff
Fix phpdbg stepping on CATCH with exception
authorBob Weinand <bobwei9@hotmail.com>
Mon, 27 Jul 2015 22:10:08 +0000 (00:10 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Mon, 27 Jul 2015 22:10:42 +0000 (00:10 +0200)
sapi/phpdbg/phpdbg_prompt.c
sapi/phpdbg/tests/stepping_001.phpt [new file with mode: 0644]

index 9253576f01e92e445f608d6058746cf2bc69804d..89e8d027f6c64f3ce9a0289465c0fb4aca14090f 100644 (file)
@@ -1384,7 +1384,11 @@ void phpdbg_clean(zend_bool full) /* {{{ */
 
 /* code may behave weirdly if EG(exception) is set */
 #define DO_INTERACTIVE(allow_async_unsafe) do { \
+       const zend_op *backup_opline; \
        if (exception) { \
+               if (EG(current_execute_data) && EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type)) { \
+                       backup_opline = EG(current_execute_data)->opline; \
+               } \
                ++GC_REFCOUNT(exception); \
                zend_clear_exception(); \
        } \
@@ -1402,8 +1406,14 @@ void phpdbg_clean(zend_bool full) /* {{{ */
                case PHPDBG_UNTIL: \
                case PHPDBG_NEXT: \
                        if (exception) { \
-                               Z_OBJ(zv) = exception; \
-                               zend_throw_exception_internal(&zv); \
+                               if (EG(current_execute_data) && EG(current_execute_data)->func && ZEND_USER_CODE(EG(current_execute_data)->func->common.type) \
+                                && (backup_opline->opcode == ZEND_HANDLE_EXCEPTION || backup_opline->opcode == ZEND_CATCH)) { \
+                                       EG(current_execute_data)->opline = backup_opline; \
+                                       EG(exception) = exception; \
+                               } else { \
+                                       Z_OBJ(zv) = exception; \
+                                       zend_throw_exception_internal(&zv); \
+                               } \
                        } \
                        /* fallthrough */ \
                default: \
diff --git a/sapi/phpdbg/tests/stepping_001.phpt b/sapi/phpdbg/tests/stepping_001.phpt
new file mode 100644 (file)
index 0000000..bc91a67
--- /dev/null
@@ -0,0 +1,65 @@
+--TEST--
+Stepping with exceptions must not be stuck at CATCH
+--PHPDBG--
+b ZEND_THROW
+r
+s
+
+
+
+
+
+
+q
+--EXPECTF--
+[Successful compilation of %s]
+prompt> [Breakpoint #0 added at ZEND_THROW]
+prompt> [Breakpoint #0 in ZEND_THROW at %s:4, hits: 1]
+>00004:        throw new Exception;
+ 00005: }
+ 00006: 
+prompt> [L0 %s HANDLE_EXCEPTION                                                                       %s]
+>00004:        throw new Exception;
+ 00005: }
+ 00006: 
+prompt> [L0 %s HANDLE_EXCEPTION                                                                       %s]
+[L9 %s CATCH                   "Exception"          $e                   1                    %s]
+>00008:        foo();
+ 00009: } catch (Exception $e) {
+ 00010:        echo "ok";
+prompt> [L10 %s ECHO                    "ok"                                                           %s]
+>00010:        echo "ok";
+ 00011: } finally {
+ 00012:        echo " ... ok";
+prompt> ok
+[L10 %s FAST_CALL               J8                                        ~1                   %s]
+[L12 %s ECHO                    " ... ok"                                                      %s]
+>00012:        echo " ... ok";
+ 00013: }
+ 00014: 
+prompt>  ... ok
+[L12 %s FAST_RET                ~1                                                             %s]
+[L10 %s JMP                     J10                                                            %s]
+>00010:        echo "ok";
+ 00011: } finally {
+ 00012:        echo " ... ok";
+prompt> [L12 %s RETURN                  1                                                              %s]
+>00012:        echo " ... ok";
+ 00013: }
+ 00014: 
+prompt> [Script ended normally]
+prompt> 
+--FILE--
+<?php
+
+function foo() {
+       throw new Exception;
+}
+
+try {
+       foo();
+} catch (Exception $e) {
+       echo "ok";
+} finally {
+       echo " ... ok";
+}