Skip to content

Infinite loop if circular reference doesn't start with top-level definition #775

@mikeharder

Description

@mikeharder

In this PR, LintDiff was hanging because @stoplight/json-ref-resolver was in an infinite loop of circular references.

Azure/azure-rest-api-specs#32573 (comment)

I believe @stoplight/json-ref-resolver can only reliably handle circular references, if the cycle includes the top-level definition in the file you are trying to resolve.

https://github.com/stoplightio/json-ref-resolver/blob/e4e2410e86edcc7a96e01d309039ad319ca40f2c/src/crawler.ts#L115-L118

In the example PR, if CommunicationErrorResponse is in a different JSON file than CommunicationError (which has a circular reference to CommunicationError), the cycle can be detected immediately. So instead of running forever, it completes on the spec in 3 seconds.

But if CommunicationErrorResponse and CommunicationError are siblings in the same JSON file, json-ref-resolver falls into a different codepath where it can't detect the cycle.

This example doesn't hang, because the cycle is ErrorResponse->ErrorResponse, and ErrorResponse is the top-level object under definitions we are resolving:

"definitions": {
"ErrorResponse": {
"properties": {
"code": {
"type": "string"
},
"detail": {
"$ref": "#/definitions/ErrorResponse"
}
}
}

However, this example should hang when trying to resolve ErrorResponse, since the cycle is ErrorResponse->Error->Error..., but since the cycle doesn't go through ErrorResponse, it isn't detected by json-ref-resolver.

  "definitions": {
    "ErrorResponse": {
      "properties": {
        "code": {
          "type": "string"
        },
        "detail": {
          "$ref": "#/definitions/Error"
        }
      },
    "Error": {
      "properties": {
        "code": {
          "type": "string"
        },
        "detail": {
          "$ref": "#/definitions/Error"
        }
      }
    }

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