php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68270 Exception from finally block has exception from try block magically injected
Submitted: 2014-10-20 16:48 UTC Modified: -
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: dan dot lugg at gmail dot com Assigned:
Status: Open Package: *General Issues
PHP Version: 5.5.18 OS: Windows 7 x64
Private report: No CVE-ID: None
 [2014-10-20 16:48 UTC] dan dot lugg at gmail dot com
Description:
------------
When an exception is thrown from a `finally` block, if an exception has been thrown from the `finally`'s corresponding `try` block, the `finally`-thrown exception magically has the `try`-thrown exception assigned as it's `$previous`.

Test script:
---------------
<?php

try {
	try {
		throw new Exception('Foo');
	}
	finally {
		throw new Exception('Bar');
	}
}
catch(Exception $exception) {
	var_dump($exception);
}

Expected result:
----------------
Not certain, but I'd guess the `finally`-thrown exception should bubble, while the `try`-thrown exception is swallowed? Perhaps a different outcome, but what occurs is both unexpected and undocumented.

Actual result:
--------------
object(Exception)#2 (7) {
  ["message":protected]=>
  string(3) "Bar"
  ["string":"Exception":private]=>
  string(0) ""
  ["code":protected]=>
  int(0)
  ["file":protected]=>
  string(9) "/in/9DMoe"
  ["line":protected]=>
  int(8)
  ["trace":"Exception":private]=>
  array(0) {
  }
  ["previous":"Exception":private]=>   <-- How is this here?
  object(Exception)#1 (7) {
    ["message":protected]=>
    string(3) "Foo"
    ["string":"Exception":private]=>
    string(0) ""
    ["code":protected]=>
    int(0)
    ["file":protected]=>
    string(9) "/in/9DMoe"
    ["line":protected]=>
    int(5)
    ["trace":"Exception":private]=>
    array(0) {
    }
    ["previous":"Exception":private]=>
    NULL
  }
}

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-10-20 16:53 UTC] Danack at basereality dot com
This happens when the 'previous' value is explicitly set to null as well.

try {
	try {
		throw new Exception('Foo');
	}
	finally {
		throw new Exception('Bar', 0, null);
	}
}
catch(Exception $exception) {
	$actualPrevious = $exception->getPrevious();
	var_dump($actualPrevious);
}


Expected
========

NULL

Actual
======


object(Exception)#1 (7) {
  ["message":protected]=>
  string(3) "Foo"
  ["string":"Exception":private]=>
  string(0) ""
  ["code":protected]=>
  int(0)
  ["file":protected]=>
  string(9) "/in/FUjgp"
  ["line":protected]=>
  int(5)
  ["trace":"Exception":private]=>
  array(0) {
  }
  ["previous":"Exception":private]=>
  NULL
}
 [2014-10-20 17:00 UTC] Danack at basereality dot com
It looks like the first construction of an Exception gets the previous, subsequent construction behaves as expected:

Code
----
function foo(){
	try {
		throw new Exception('First exception');
	}
	finally {
		throw new Exception('Bar', 0, new Exception("This shouldn't have a previous."));
	}

}

try {
   foo();
}
catch(Exception $exception) {
	while ($exception = $exception->getPrevious()) {
        echo $exception->getMessage().PHP_EOL;
    }
}


Expected
--------
This shouldn't have a previous.

Actual
------
This shouldn't have a previous.
First exception
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 28 05:01:28 2024 UTC