try/catch not working with two exceptions inside a same operation

 [2016-10-18 10:27 UTC] bwoebi@php.net

Description:
------------
If two exceptions happen to be thrown inside a same opcode (the last one of both *must* be thrown from within a separate function, e.g. an userland destructor).

The bug is in zend_throw_exception_internal(). We do not overwrite EG(opline_before_exception) in case the current opcode is ZEND_HANDLE_EXCEPTION.
This is problematic in the case we aren't yet at that opcode, but it just got set to it by a previous call to zend_throw_exception_internal(). I.e. in case one exception has been triggered and then another exception is thrown within the same opcode.
This leads to throw_op_num (= EG(opline_before_exception) - EX(func)->op_array.opcodes) inside ZEND_HANDLE_EXCEPTION opcode being bogus and catching does not work thus.

Test script:
---------------
class d { function __destruct() { throw new Error; } }
try { new d + new d; } catch (Error $e) { print "Exception properly caught"; }

Expected result:
----------------
Exception properly caught

Actual result:
--------------
Fatal error: Uncaught Error in Command line code:1
Stack trace:
#0 Command line code(1): d->__destruct()
#1 {main}

Next Error in Command line code:1
Stack trace:
#0 Command line code(1): d->__destruct()
#1 {main}
  thrown in Command line code on line 1