diff --git a/src/JsonSchema/SchemaStorage.php b/src/JsonSchema/SchemaStorage.php index 9a1caeb4..de2a1cb2 100644 --- a/src/JsonSchema/SchemaStorage.php +++ b/src/JsonSchema/SchemaStorage.php @@ -94,7 +94,7 @@ public function getSchema($id) /** * {@inheritdoc} */ - public function resolveRef($ref) + public function resolveRef($ref, $resolveStack = array()) { $jsonPointer = new JsonPointer($ref); @@ -111,9 +111,9 @@ public function resolveRef($ref) $refSchema = $this->getSchema($fileName); foreach ($jsonPointer->getPropertyPaths() as $path) { if (is_object($refSchema) && property_exists($refSchema, $path)) { - $refSchema = $this->resolveRefSchema($refSchema->{$path}); + $refSchema = $this->resolveRefSchema($refSchema->{$path}, $resolveStack); } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) { - $refSchema = $this->resolveRefSchema($refSchema[$path]); + $refSchema = $this->resolveRefSchema($refSchema[$path], $resolveStack); } else { throw new UnresolvableJsonPointerException(sprintf( 'File: %s is found, but could not resolve fragment: %s', @@ -129,12 +129,18 @@ public function resolveRef($ref) /** * {@inheritdoc} */ - public function resolveRefSchema($refSchema) + public function resolveRefSchema($refSchema, $resolveStack = array()) { if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) { - $newSchema = $this->resolveRef($refSchema->{'$ref'}); - $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema)); - unset($refSchema->{'$ref'}); + if (in_array($refSchema, $resolveStack, true)) { + throw new UnresolvableJsonPointerException(sprintf( + 'Dereferencing a pointer to %s results in an infinite loop', + $refSchema->{'$ref'} + )); + } + $resolveStack[] = $refSchema; + + return $this->resolveRef($refSchema->{'$ref'}, $resolveStack); } return $refSchema; diff --git a/tests/RefTest.php b/tests/RefTest.php new file mode 100644 index 00000000..b67852c1 --- /dev/null +++ b/tests/RefTest.php @@ -0,0 +1,78 @@ +setExpectedException($exception); + } + + $v->validate($document, $schema); + + $this->assertEquals($isValid, $v->isValid()); + } +} diff --git a/tests/SchemaStorageTest.php b/tests/SchemaStorageTest.php index 0e440ac8..9fd27bae 100644 --- a/tests/SchemaStorageTest.php +++ b/tests/SchemaStorageTest.php @@ -79,7 +79,7 @@ public function testSchemaWithLocalAndExternalReferencesWithCircularReference() ); // local ref with overriding - $this->assertNotEquals( + $this->assertEquals( $schemaStorage->resolveRef("$mainSchemaPath#/definitions/house/additionalProperties"), $schemaStorage->resolveRef("$mainSchemaPath#/properties/house/additionalProperties") );