Fix zend_vm_call_opcode_handler (e.g. Generators throwing exceptions) with IP/FP...
authorBob Weinand <bobwei9@hotmail.com>
Tue, 25 Aug 2015 23:25:25 +0000 (00:25 +0100)
committerBob Weinand <bobwei9@hotmail.com>
Tue, 25 Aug 2015 23:25:25 +0000 (00:25 +0100)
Zend/zend_vm_execute.h
Zend/zend_vm_gen.php
sapi/phpdbg/tests/generator_run.phpt [new file with mode: 0644]

index fef3e96bc7fac3248db2f6bf3a1a728407383522..f85d6c0a2c1c95aa7a83314782a37d14664b1e7a 100644 (file)
@@ -49636,11 +49636,16 @@ ZEND_API int zend_vm_call_opcode_handler(zend_execute_data* ex)
        LOAD_OPLINE();
 #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)
        ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-       ret = opline? ((execute_data != ex)? (int)(execute_data->prev_execute_data != ex) + 1 : 0) : -1;
+       if (EXPECTED(opline)) {
+               ret = execute_data != ex ? (int)(execute_data->prev_execute_data != ex) + 1 : 0;
+               SAVE_OPLINE();
+       } else {
+               ret = -1;
+       }
 #else
        ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-#endif
        SAVE_OPLINE();
+#endif
 #ifdef ZEND_VM_FP_GLOBAL_REG
        execute_data = orig_execute_data;
 #endif
index 3a80705b6a204a82882987534fdbfad54f6296b6..40c9f24f534d740547a997a4f504785dfc72f772 100644 (file)
@@ -1618,11 +1618,16 @@ function gen_vm($def, $skel) {
                out($f, "\tLOAD_OPLINE();\n");
                out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
                out($f, "\t((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
-               out($f, "\tret = opline? ((execute_data != ex)? (int)(execute_data->prev_execute_data != ex) + 1 : 0) : -1;\n");
+               out($f, "\tif (EXPECTED(opline)) {\n");
+               out($f, "\t\tret = execute_data != ex ? (int)(execute_data->prev_execute_data != ex) + 1 : 0;\n");
+               out($f, "\t\tSAVE_OPLINE();\n");
+               out($f, "\t} else {\n");
+               out($f, "\t\tret = -1;\n");
+               out($f, "\t}\n");
                out($f, "#else\n");
                out($f, "\tret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
-               out($f, "#endif\n");
                out($f, "\tSAVE_OPLINE();\n");
+               out($f, "#endif\n");
                out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n");
                out($f, "\texecute_data = orig_execute_data;\n");
                out($f, "#endif\n");
diff --git a/sapi/phpdbg/tests/generator_run.phpt b/sapi/phpdbg/tests/generator_run.phpt
new file mode 100644 (file)
index 0000000..798d770
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+Ensure proper saving of EX(opline)
+--PHPDBG--
+r
+q
+--EXPECTF--
+[Successful compilation of %s]
+prompt> caught Generator exception
+[Script ended normally]
+prompt> 
+--FILE--
+<?php
+
+function gen() {
+       try {
+               throw new Exception;
+       } catch(Exception $e) {
+               yield "caught Generator exception";
+       }
+}
+
+foreach (gen() as $v) {
+       print $v;
+}