Skip to content

Response validation with circular $ref definition causes infinite loop #531

Closed
@MaikWagner

Description

@MaikWagner

Hi,

I was trying to validate a response with a json schema that has circular $ref definitions. This is basically allowed (https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03#section-7) but leads to an php error after looping infinitely:

PHP Fatal error: Maximum execution time of 30 seconds exceeded in vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php on line 85

With xdebug enabled it exits after a while and throws this backtrace:

PHP Fatal error: Uncaught Error: Maximum function nesting level of '256' reached, aborting! in /vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php:86
Stack trace:
#0 vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php(86): is_object('id')
#1 vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php(89): JsonSchema\SchemaStorage->expandRefs('id', 'internal://prov...')
#2 vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php(107): JsonSchema\SchemaStorage->expandRefs(Array, 'internal://prov...')
#3 vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php(107): JsonSchema\SchemaStorage->expandRefs(Object(stdClass), 'internal://prov...')
#4 vendor/justinrainbow/json-schema/src/JsonSchema/SchemaSto in vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php on line 86

schema-loop-debug

test.php

<?php
require __DIR__ . '/vendor/autoload.php';

$data = json_decode(file_get_contents('data.json'));
$validator = new JsonSchema\Validator();
$validator->validate($data, (object) array('$ref' => 'file://' . realpath('swagger.json')));

//everything is ok
print("schema validation (input): " . var_export($validator->isValid(),1) . "\n");

//Request validation causes endless loop
$response = new Response(200, [], "", "/ps?hash=123", 'GET');

$validator = new SwaggerValidator('file://' . realpath('swagger.json'));

if ($result = $validator->validateResponse($response)) {
        print("ok\n");
} else {
        fprintf(STDERR, implode(', ', $validator->getErrors()) . "\n");
        exit(1);
}

swagger.json

{
  "swagger": "2.0",
  "info": {
    "title": "Test",
    "version": "0.0.1"
  },
  "paths": {
    "/ps": {
      "get": {
        "parameters": [
          {
            "in": "query",
            "name":"name",
            "type": "string"
          }
        ],
        "responses": {
          "200": {
            "description": "foo",
            "schema": {
              "$ref": "#/definitions/actionItem"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "response": {
    },
    "actionItem": {
      "type": "object",
      "required": [
        "name"
      ],
      "properties": {
        "name": {
          "type": "string"
        },
        "refs": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/actionItem"
          }
        }
      }
    }
  }
}

data.json

{ "name":"John", "age":30, "car":null }

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions