From 07ada5e3482337b26d7c0bb0142c5e425237e01b Mon Sep 17 00:00:00 2001 From: lalshe Date: Wed, 4 Dec 2019 20:36:35 +0200 Subject: [PATCH] More strict check for serialized data. More clear psalm annotations usage. `message:array` can be changed to `message:array` after https://github.com/vimeo/psalm/issues/2409 resolved in psalm --- src/Symfony/SymfonyMessageSerializer.php | 15 ++++++++-- .../Symfony/SymfonyMessageSerializerTest.php | 28 ++++++++++++++++++- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/Symfony/SymfonyMessageSerializer.php b/src/Symfony/SymfonyMessageSerializer.php index da0c466..a17427b 100644 --- a/src/Symfony/SymfonyMessageSerializer.php +++ b/src/Symfony/SymfonyMessageSerializer.php @@ -92,7 +92,6 @@ public function decode(string $serializedMessage): object { try { - /** @psalm-var array{message:array, namespace:class-string} $data */ $data = $this->serializer->unserialize($serializedMessage); self::validateUnserializedData($data); @@ -162,7 +161,7 @@ public function normalize(object $message): array } /** - * @psalm-param array{message:array, namespace:class-string} $data + * @psalm-assert array{message:array, namespace:class-string} $data * * @throws \UnexpectedValueException */ @@ -178,12 +177,22 @@ private static function validateUnserializedData(array $data): void ); } + if (false === \is_array($data['message'])) + { + throw new \UnexpectedValueException('"message" field from serialized data should be an array'); + } + + if (false === \is_string($data['namespace'])) + { + throw new \UnexpectedValueException('"namespace" field from serialized data should be a string'); + } + /** * Let's check if the specified class exists. * * @psalm-suppress DocblockTypeContradiction */ - if ($data['namespace'] === '' || \class_exists((string) $data['namespace']) === false) + if ($data['namespace'] === '' || \class_exists($data['namespace']) === false) { throw new \UnexpectedValueException( \sprintf('Class "%s" not found', $data['namespace']) diff --git a/tests/Symfony/SymfonyMessageSerializerTest.php b/tests/Symfony/SymfonyMessageSerializerTest.php index 934ee95..f1252f8 100644 --- a/tests/Symfony/SymfonyMessageSerializerTest.php +++ b/tests/Symfony/SymfonyMessageSerializerTest.php @@ -72,6 +72,32 @@ public static function classWithClosedConstructor(): void ); } + /** + * @test + * + * @throws \Throwable + */ + public function messageNotArray(): void + { + $this->expectException(DecodeMessageFailed::class); + $this->expectExceptionMessage('"message" field from serialized data should be an array'); + + (new SymfonyMessageSerializer())->decode(\json_encode(['message' => 'someValue', 'namespace' => \SomeClass::class])); + } + + /** + * @test + * + * @throws \Throwable + */ + public function namespaceNotString(): void + { + $this->expectException(DecodeMessageFailed::class); + $this->expectExceptionMessage('"namespace" field from serialized data should be a string'); + + (new SymfonyMessageSerializer())->decode(\json_encode(['message' => [], 'namespace' => new \stdClass])); + } + /** * @test * @@ -82,7 +108,7 @@ public function classNotFound(): void $this->expectException(DecodeMessageFailed::class); $this->expectExceptionMessage('Class "SomeClass" not found'); - (new SymfonyMessageSerializer())->decode(\json_encode(['message' => 'someValue', 'namespace' => \SomeClass::class])); + (new SymfonyMessageSerializer())->decode(\json_encode(['message' => [], 'namespace' => \SomeClass::class])); } /**