diff --git a/CHANGELOG.md b/CHANGELOG.md index fa4baed2f..4dc1e0f70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] ### Fixed + - Substitute invalid UTF-8 in JSON error renderer output (#811) ### Added diff --git a/Slim/Error/Renderers/JsonErrorRenderer.php b/Slim/Error/Renderers/JsonErrorRenderer.php index 06085d2e5..4902c8a61 100644 --- a/Slim/Error/Renderers/JsonErrorRenderer.php +++ b/Slim/Error/Renderers/JsonErrorRenderer.php @@ -16,6 +16,7 @@ use function get_class; use function json_encode; +use const JSON_INVALID_UTF8_SUBSTITUTE; use const JSON_PRETTY_PRINT; use const JSON_UNESCAPED_SLASHES; @@ -35,7 +36,10 @@ public function __invoke(Throwable $exception, bool $displayErrorDetails): strin } while ($exception = $exception->getPrevious()); } - return (string) json_encode($error, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES); + return (string) json_encode( + $error, + JSON_INVALID_UTF8_SUBSTITUTE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES + ); } /** diff --git a/tests/Error/AbstractErrorRendererTest.php b/tests/Error/AbstractErrorRendererTest.php index f47fee4c8..aa9e1dfd3 100644 --- a/tests/Error/AbstractErrorRendererTest.php +++ b/tests/Error/AbstractErrorRendererTest.php @@ -163,6 +163,23 @@ public function testJSONErrorRendererDoesNotDisplayErrorDetails() $this->assertSame($output, json_encode(['message' => 'Slim Application Error'])); } + public function testJSONErrorRendererSubstitutesInvalidUtf8() + { + $exception = new Exception("Invalid \xB1\x31 UTF-8 sequence"); + + $renderer = new JsonErrorRenderer(); + $output = $renderer->__invoke($exception, true); + + $this->assertNotSame('', $output); + $decoded = json_decode($output, true); + $this->assertIsArray($decoded); + $this->assertSame('Slim Application Error', $decoded['message']); + $this->assertSame( + "Invalid \u{FFFD}1 UTF-8 sequence", + $decoded['exception'][0]['message'] + ); + } + public function testJSONErrorRendererDisplaysPreviousError() { $previousException = new Exception('Oh no!');