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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions