瀏覽代碼

Fix json formatter does not catch to string exceptions (#1968)

* fix: JsonFormatter does not catch toString exceptions

* test: test JsonFormatter toString handling

---------

Co-authored-by: Adrien SIMON <asimon@worldia.com>
Adrien SIMON 1 周之前
父節點
當前提交
05c6b18896
共有 2 個文件被更改,包括 32 次插入1 次删除
  1. 5 1
      src/Monolog/Formatter/JsonFormatter.php
  2. 27 0
      tests/Monolog/Formatter/JsonFormatterTest.php

+ 5 - 1
src/Monolog/Formatter/JsonFormatter.php

@@ -195,7 +195,11 @@ class JsonFormatter extends NormalizerFormatter
             }
 
             if ($data instanceof Stringable) {
-                return $data->__toString();
+                try {
+                    return $data->__toString();
+                } catch (Throwable) {
+                    return $data::class;
+                }
             }
 
             if (\get_class($data) === '__PHP_Incomplete_Class') {

+ 27 - 0
tests/Monolog/Formatter/JsonFormatterTest.php

@@ -11,6 +11,7 @@
 
 namespace Monolog\Formatter;
 
+use Exception;
 use Monolog\Level;
 use Monolog\LogRecord;
 use JsonSerializable;
@@ -338,6 +339,24 @@ class JsonFormatterTest extends MonologTestCase
             $record
         );
     }
+
+    public function testNormalizeHandleExceptionInToString(): void
+    {
+        $formatter = new JsonFormatter();
+
+        $res = $formatter->format($this->getRecord(
+            Level::Critical,
+            'bar',
+            datetime: new \DateTimeImmutable('2025-05-19 00:00:00'),
+            channel: 'test',
+            context: ['object' => new TestJsonNormWithFailingToString],
+        ));
+
+        $this->assertSame(
+            '{"message":"bar","context":{"object":"Monolog\\\\Formatter\\\\TestJsonNormWithFailingToString"},"level":500,"level_name":"CRITICAL","channel":"test","datetime":"2025-05-19T00:00:00+00:00","extra":{}}'."\n",
+            $res,
+        );
+    }
 }
 
 class TestJsonNormPublic
@@ -370,3 +389,11 @@ class TestJsonNormWithToString
         return 'stringified';
     }
 }
+
+class TestJsonNormWithFailingToString
+{
+    public function __toString()
+    {
+        throw new Exception('Whatever');
+    }
+}