From a2cfbf6fad79f6461081f967e94f1f80aa70973f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=B6ller?= Date: Tue, 9 Oct 2018 17:58:53 +0100 Subject: [PATCH 1/2] Enhancement: Assert that normalization of JSON is skipped when not decoding to object --- .../Normalizer/AbstractNormalizerTestCase.php | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/test/Unit/Normalizer/AbstractNormalizerTestCase.php b/test/Unit/Normalizer/AbstractNormalizerTestCase.php index 5e4733c6..cfb93a47 100644 --- a/test/Unit/Normalizer/AbstractNormalizerTestCase.php +++ b/test/Unit/Normalizer/AbstractNormalizerTestCase.php @@ -33,9 +33,7 @@ final public function testNormalizeRejectsInvalidJson(): void { $json = $this->faker()->realText(); - $reflection = new \ReflectionClass($this->className()); - - $normalizer = $reflection->newInstanceWithoutConstructor(); + $normalizer = $this->createNormalizer(); $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage(\sprintf( @@ -46,6 +44,41 @@ final public function testNormalizeRejectsInvalidJson(): void $normalizer->normalize($json); } + /** + * @dataProvider providerJsonNotDecodingToObject + * + * @param string $json + */ + final public function testNormalizeDoesNotModifyWhenJsonDecodedIsNotAnObject(string $json): void + { + $normalizer = $this->createNormalizer(); + + $normalized = $normalizer->normalize($json); + + $this->assertSame($json, $normalized); + } + + public function providerJsonNotDecodingToObject(): \Generator + { + $faker = $this->faker(); + + $values = [ + 'array' => $faker->words, + 'bool-false' => false, + 'bool-true' => true, + 'float' => $faker->randomFloat(), + 'int' => $faker->randomNumber(), + 'null' => null, + 'string' => $faker->sentence, + ]; + + foreach ($values as $key => $value) { + yield $key => [ + \json_encode($value), + ]; + } + } + final protected function className(): string { return \preg_replace( @@ -58,4 +91,11 @@ final protected function className(): string ) ); } + + private function createNormalizer(): Normalizer\NormalizerInterface + { + $reflection = new \ReflectionClass($this->className()); + + return $reflection->newInstanceWithoutConstructor(); + } } From b3c12a35245099987ffce747d9e6d7f5b576ab02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20M=C3=B6ller?= Date: Tue, 9 Oct 2018 18:12:35 +0100 Subject: [PATCH 2/2] Fix: Return early when json_decode()'ed data is not an object --- phpstan.neon | 4 ++++ src/Normalizer/BinNormalizer.php | 5 ++++- src/Normalizer/ComposerJsonNormalizer.php | 8 +++++++- src/Normalizer/ConfigHashNormalizer.php | 4 ++++ src/Normalizer/PackageHashNormalizer.php | 4 ++++ src/Normalizer/VersionConstraintNormalizer.php | 4 ++++ 6 files changed, 27 insertions(+), 2 deletions(-) diff --git a/phpstan.neon b/phpstan.neon index 96d0543a..c0dc08e2 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,2 +1,6 @@ includes: - vendor/phpstan/phpstan-strict-rules/rules.neon + +parameters: + ignoreErrors: + - '#Access to an undefined property object::\$bin.#' diff --git a/src/Normalizer/BinNormalizer.php b/src/Normalizer/BinNormalizer.php index fbcf593b..ddd7623b 100644 --- a/src/Normalizer/BinNormalizer.php +++ b/src/Normalizer/BinNormalizer.php @@ -28,7 +28,10 @@ public function normalize(string $json): string )); } - if (!\property_exists($decoded, 'bin') || !\is_array($decoded->bin)) { + if (!\is_object($decoded) + || !\property_exists($decoded, 'bin') + || !\is_array($decoded->bin) + ) { return $json; } diff --git a/src/Normalizer/ComposerJsonNormalizer.php b/src/Normalizer/ComposerJsonNormalizer.php index f62825bf..9f61d37d 100644 --- a/src/Normalizer/ComposerJsonNormalizer.php +++ b/src/Normalizer/ComposerJsonNormalizer.php @@ -35,13 +35,19 @@ public function __construct(string $schemaUri = 'https://getcomposer.org/schema. public function normalize(string $json): string { - if (null === \json_decode($json) && \JSON_ERROR_NONE !== \json_last_error()) { + $decoded = \json_decode($json); + + if (null === $decoded && \JSON_ERROR_NONE !== \json_last_error()) { throw new \InvalidArgumentException(\sprintf( '"%s" is not valid JSON.', $json )); } + if (!\is_object($decoded)) { + return $json; + } + return $this->normalizer->normalize($json); } } diff --git a/src/Normalizer/ConfigHashNormalizer.php b/src/Normalizer/ConfigHashNormalizer.php index cf99505f..fe328eda 100644 --- a/src/Normalizer/ConfigHashNormalizer.php +++ b/src/Normalizer/ConfigHashNormalizer.php @@ -36,6 +36,10 @@ public function normalize(string $json): string )); } + if (!\is_object($decoded)) { + return $json; + } + $objectProperties = \array_intersect_key( \get_object_vars($decoded), \array_flip(self::$properties) diff --git a/src/Normalizer/PackageHashNormalizer.php b/src/Normalizer/PackageHashNormalizer.php index de1b8c87..4f6cc860 100644 --- a/src/Normalizer/PackageHashNormalizer.php +++ b/src/Normalizer/PackageHashNormalizer.php @@ -41,6 +41,10 @@ public function normalize(string $json): string )); } + if (!\is_object($decoded)) { + return $json; + } + $objectProperties = \array_intersect_key( \get_object_vars($decoded), \array_flip(self::$properties) diff --git a/src/Normalizer/VersionConstraintNormalizer.php b/src/Normalizer/VersionConstraintNormalizer.php index 6fa9a3d8..85083f71 100644 --- a/src/Normalizer/VersionConstraintNormalizer.php +++ b/src/Normalizer/VersionConstraintNormalizer.php @@ -57,6 +57,10 @@ public function normalize(string $json): string )); } + if (!\is_object($decoded)) { + return $json; + } + $objectProperties = \array_intersect_key( \get_object_vars($decoded), \array_flip(self::$properties)