/** * Wrapper around unserialize() that converts syntax errors to exceptions. * * @param string $input Serialized string * * @return mixed * * @throws SyntaxError If there was an error unserializing the string */ function unserialize($input) { static $exceptionFactory; $currentHandler = null; if (null === $exceptionFactory) { $exceptionFactory = new SyntaxErrorFactory(); } if (defined('HHVM_VERSION')) { // @codeCoverageIgnoreStart $errorHandler = function ($code, $message, $file, $line) use($exceptionFactory, &$currentHandler, $input) { if ($code === E_NOTICE) { throw $exceptionFactory->create($input, $message); } if ($currentHandler) { return call_user_func_array($currentHandler, func_get_args()); } return false; }; } else { // @codeCoverageIgnoreEnd static $errorHandler; if (!$errorHandler) { $errorHandler = function ($code, $message, $file, $line) use($exceptionFactory, &$currentHandler) { if ($code === E_NOTICE) { $e = new \ErrorException($message, $code, 0, $file, $line); throw $exceptionFactory->createFromErrorException($e); } if ($currentHandler) { return call_user_func_array($currentHandler, func_get_args()); } // @codeCoverageIgnoreStart return false; // @codeCoverageIgnoreEnd }; } } $currentHandler = set_error_handler($errorHandler); try { $result = \unserialize($input); if ($result === false && $input !== 'b:0;') { throw new UnknownException($input, 'Unknown error was encountered'); } } catch (\Exception $e) { throw $e; } finally { // Ensure the error handler is restored. restore_error_handler(); } return $result; }
/** * @dataProvider dataCreateErrorAtOffset */ public function testCreateErrorAtOffset($input, $message, $offset) { $this->skipOnHhvm(); // Sanity check as the set_error_handler() call breaks PHPUnit's // exception catching. $this->assertInternalType('string', $input); set_error_handler(function ($code, $message, $file, $line) { throw new \ErrorException($message, E_NOTICE, 0, '', 0); }, E_NOTICE); try { \unserialize($input); } catch (\ErrorException $error) { restore_error_handler(); $factory = new SyntaxErrorFactory(); $exception = $factory->createFromErrorException($error); $this->assertInstanceOf(SyntaxError::class, $exception); $this->assertInstanceOf(ErrorAtOffsetException::class, $exception); $this->assertSame($input, $exception->getInput()); $this->assertSame($offset, $exception->getOffset()); $this->assertSame($message, $exception->getMessage() . ":\n\n" . $exception->getSnippet()); $this->assertInstanceOf('ErrorException', $exception->getPrevious()); return; // Normal test execution ends here. } restore_error_handler(); $this->fail('No error was raised'); }