diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index c33a3565079c..ad4d87c207dd 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -82,7 +82,7 @@ public function encode(mixed $data, string $format, array $context = []): string $encoderIgnoredNodeTypes = $context[self::ENCODER_IGNORED_NODE_TYPES] ?? $this->defaultContext[self::ENCODER_IGNORED_NODE_TYPES]; $ignorePiNode = \in_array(\XML_PI_NODE, $encoderIgnoredNodeTypes, true); if ($data instanceof \DOMDocument) { - return $data->saveXML($ignorePiNode ? $data->documentElement : null); + return $this->saveXml($data, $ignorePiNode ? $data->documentElement : null); } $xmlRootNodeName = $context[self::ROOT_NODE_NAME] ?? $this->defaultContext[self::ROOT_NODE_NAME]; @@ -97,7 +97,7 @@ public function encode(mixed $data, string $format, array $context = []): string $this->appendNode($dom, $data, $format, $context, $xmlRootNodeName); } - return $dom->saveXML($ignorePiNode ? $dom->documentElement : null, $context[self::SAVE_OPTIONS] ?? $this->defaultContext[self::SAVE_OPTIONS]); + return $this->saveXml($dom, $ignorePiNode ? $dom->documentElement : null, $context[self::SAVE_OPTIONS] ?? $this->defaultContext[self::SAVE_OPTIONS]); } public function decode(string $data, string $format, array $context = []): mixed @@ -498,4 +498,23 @@ private function createDomDocument(array $context): \DOMDocument return $document; } + + /** + * @throws NotEncodableValueException + */ + private function saveXml(\DOMDocument $document, ?\DOMNode $node = null, ?int $options = null): string + { + $prevErrorHandler = set_error_handler(static function ($type, $message, $file, $line, $context = []) use (&$prevErrorHandler) { + if (\E_ERROR === $type || \E_WARNING === $type) { + throw new NotEncodableValueException($message); + } + + return $prevErrorHandler ? $prevErrorHandler($type, $message, $file, $line, $context) : false; + }); + try { + return $document->saveXML($node, $options); + } finally { + restore_error_handler(); + } + } } diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php index 97de86abf036..f0ff1c5b9436 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -433,6 +433,12 @@ public function testEncodeTraversableWhenNormalizable() $this->assertEquals($expected, $serializer->serialize(new NormalizableTraversableDummy(), 'xml')); } + public function testEncodeException() + { + $this->expectException(NotEncodableValueException::class); + $this->encoder->encode('Invalid character: '.\chr(7), 'xml'); + } + public function testDecode() { $source = $this->getXmlSource();