Bug #76502 [NEW]: Chain of mixed exceptions and errors does not serialize properly
| From: | benjamin dot zikarsky at jaumo dot com | Date: | Wed, 20 Jun 2018 07:52:16 +0000 |
| Subject: | Bug #76502 [NEW]: Chain of mixed exceptions and errors does not serialize properly | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-215803@lists.php.net to get a copy of this message | ||
From: benjamin dot zikarsky at jaumo dot com
Operating system: Linux 4.16
PHP version: 7.2.6
Package: *General Issues
Bug Type: Bug
Bug description:Chain of mixed exceptions and errors does not serialize properly
Description:
------------
In some error-cases we try to send serialized exceptions from our
background worker infrastructure to our webservers, where those get
deserialized and rethrown.
This usually works fine but recently we came around strange, cut-off
exception-chains. When we debugged the problem, we realized that if an
Error gets thrown, and later is wrapped into an Exception, this Error is
lost in the serialization/deserialization process. Further analysis
showed that while the error/exception chain gets serialized properly,
the
__wakeup implementation replaces Error-objects in
Exception-objects with NULL and vice-versa.
See:
https://github.com/php/php-src/blob/d04917c7b361fd07e098fe29ae931fb6fac1d9e0/Zend/zend_exceptions.c#L327-L331
https://github.com/php/php-src/blob/d04917c7b361fd07e098fe29ae931fb6fac1d9e0/Zend/zend_exceptions.c#L63-L66
While an Error wrapping an Exception may be uncommon, the Error wrapped
in an Exception is a common pattern in our codebase. With $previous
being defined as Throwable, the problem is unexpected.
Proposition: Replace `instanceof_function(Z_OBJCE_P(pvalue),
i_get_exception_base(object)` with
instanceof_function(Z_OBJCE_P(pvalue), THROWABLE. my understanding of
php-src is not good enough to fix this, but THROWABLE should be replaced
with a reference to the Throwable interface.
Test script:
---------------
<?php
$examples = [
"Exception(Exception())" => new Exception("outer", 0, new
Exception("inner")),
"Error(Error())" => new Error("outer", 0, new
Error("inner")),
"Error(Exception())" => new Error("outer", 0, new
Exception("inner")),
"Exception(Error())" => new Exception("outer", 0, new
Error("inner"))
];
foreach ($examples as $name => $example) {
$processed = unserialize(serialize($example));
$processedPrev = $processed->getPrevious();
echo "---- $name ----\n";
echo "before: ", get_class($example), ".previous == ",
get_class($example->getPrevious()), "\n";
echo "after : ", get_class($processed), ".previous == ",
$processedPrev ? get_class($processedPrev) : "null", "\n";
}
Expected result:
----------------
---- Exception(Exception()) ----
before: Exception.previous == Exception
after : Exception.previous == Exception
---- Error(Error()) ----
before: Error.previous == Error
after : Error.previous == Error
---- Error(Exception()) ----
before: Error.previous == Exception
after : Error.previous == Error
---- Exception(Error()) ----
before: Exception.previous == Error
after : Exception.previous == Exception
Actual result:
--------------
---- Exception(Exception()) ----
before: Exception.previous == Exception
after : Exception.previous == Exception
---- Error(Error()) ----
before: Error.previous == Error
after : Error.previous == Error
---- Error(Exception()) ----
before: Error.previous == Exception
after : Error.previous == null
---- Exception(Error()) ----
before: Exception.previous == Error
after : Exception.previous == null
--
Edit bug report at https://bugs.php.net/bug.php?id=76502&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=76502&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=76502&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=76502&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=76502&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=76502&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=76502&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=76502&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=76502&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=76502&r=support
Expected behavior: https://bugs.php.net/fix.php?id=76502&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=76502&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=76502&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=76502&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=76502&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=76502&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=76502&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=76502&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=76502&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=76502&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=76502&r=mysqlcfg