bug #40065 [ErrorHandler] fix handling messages with null bytes from anonymous classes (nicolas-grekas)
This PR was merged into the 4.4 branch.
Discussion
----------
[ErrorHandler] fix handling messages with null bytes from anonymous classes
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | -
| License | MIT
| Doc PR | -
PHP truncates error messages at null bytes before calling userland error handlers (known behavior in PHP, marked as "won't fix".)
This doesn't play well with anonymous classes.
This PR works around the issue by getting the message from the stack trace.
Commits
-------
ac94746dc7
[ErrorHandler] fix handling messages with null bytes from anonymous classes
This commit is contained in:
commit
6ce4d38d29
@ -422,11 +422,7 @@ class ErrorHandler
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false !== strpos($message, "@anonymous\0")) {
|
$logMessage = $this->levels[$type].': '.$message;
|
||||||
$logMessage = $this->parseAnonymousClass($message);
|
|
||||||
} else {
|
|
||||||
$logMessage = $this->levels[$type].': '.$message;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== self::$toStringException) {
|
if (null !== self::$toStringException) {
|
||||||
$errorAsException = self::$toStringException;
|
$errorAsException = self::$toStringException;
|
||||||
@ -455,6 +451,23 @@ class ErrorHandler
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (false !== strpos($message, '@anonymous')) {
|
||||||
|
$backtrace = debug_backtrace(false, 5);
|
||||||
|
|
||||||
|
for ($i = 1; isset($backtrace[$i]); ++$i) {
|
||||||
|
if (isset($backtrace[$i]['function'], $backtrace[$i]['args'][0])
|
||||||
|
&& ('trigger_error' === $backtrace[$i]['function'] || 'user_error' === $backtrace[$i]['function'])
|
||||||
|
) {
|
||||||
|
if ($backtrace[$i]['args'][0] !== $message) {
|
||||||
|
$message = $this->parseAnonymousClass($backtrace[$i]['args'][0]);
|
||||||
|
$logMessage = $this->levels[$type].': '.$message;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
|
$errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
|
||||||
|
|
||||||
if ($throw || $this->tracedErrors & $type) {
|
if ($throw || $this->tracedErrors & $type) {
|
||||||
|
@ -368,11 +368,12 @@ class ErrorHandlerTest extends TestCase
|
|||||||
|
|
||||||
public function testHandleErrorWithAnonymousClass()
|
public function testHandleErrorWithAnonymousClass()
|
||||||
{
|
{
|
||||||
|
$anonymousObject = new class() extends \stdClass {
|
||||||
|
};
|
||||||
|
|
||||||
$handler = ErrorHandler::register();
|
$handler = ErrorHandler::register();
|
||||||
$handler->throwAt(3, true);
|
|
||||||
try {
|
try {
|
||||||
$handler->handleError(3, 'foo '.\get_class(new class() extends \stdClass {
|
trigger_error('foo '.\get_class($anonymousObject).' bar', \E_USER_WARNING);
|
||||||
}).' bar', 'foo.php', 12);
|
|
||||||
$this->fail('Exception expected.');
|
$this->fail('Exception expected.');
|
||||||
} catch (\ErrorException $e) {
|
} catch (\ErrorException $e) {
|
||||||
} finally {
|
} finally {
|
||||||
@ -380,10 +381,7 @@ class ErrorHandlerTest extends TestCase
|
|||||||
restore_exception_handler();
|
restore_exception_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->assertSame('foo stdClass@anonymous bar', $e->getMessage());
|
$this->assertSame('User Warning: foo stdClass@anonymous bar', $e->getMessage());
|
||||||
$this->assertSame(3, $e->getSeverity());
|
|
||||||
$this->assertSame('foo.php', $e->getFile());
|
|
||||||
$this->assertSame(12, $e->getLine());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testHandleDeprecation()
|
public function testHandleDeprecation()
|
||||||
|
Reference in New Issue
Block a user