everit-org/json-schema

$id and $ref with same value will lead to StackOverFlowError when visit combined schema.

counter2015 opened this issue · 2 comments

The schema file

{
  "$id": "https://raw.githubusercontent.com/cloudevents/spec/main/cloudevents/formats/cloudevents.json",
  "allOf": [
    {
      "$ref": "https://raw.githubusercontent.com/cloudevents/spec/main/cloudevents/formats/cloudevents.json"
    }
  ]
}

The code

import org.everit.json.schema.loader.SchemaLoader;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.io.IOException;

public class Bug {

    static void check() {
        try (var inputStream = Bug.class.getResourceAsStream("schema.json")) {
            var rawSchema = new JSONObject(new JSONTokener(inputStream));
            var schema = SchemaLoader.builder().schemaJson(rawSchema).draftV7Support().build().load().build();
            schema.validate(new JSONObject("{\"hello\" : \"world\"}"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        check();
    }
}

It will raise error like following

Exception in thread "main" java.lang.StackOverflowError
	at org.everit.json.schema.ValidatingVisitor.visitCombinedSchema(ValidatingVisitor.java:160)
	at org.everit.json.schema.CombinedSchema.accept(CombinedSchema.java:200)
	at org.everit.json.schema.Visitor.visit(Visitor.java:48)
	at org.everit.json.schema.ValidatingVisitor.visit(ValidatingVisitor.java:59)
	at org.everit.json.schema.ValidatingVisitor.lambda$getFailureOfSchema$2(ValidatingVisitor.java:199)
	at org.everit.json.schema.ValidationFailureReporter.inContextOfSchema(ValidationFailureReporter.java:34)
	at org.everit.json.schema.CollectingFailureReporter.inContextOfSchema(CollectingFailureReporter.java:25)
	at org.everit.json.schema.ValidatingVisitor.getFailureOfSchema(ValidatingVisitor.java:199)
	at org.everit.json.schema.ValidatingVisitor.visitReferenceSchema(ValidatingVisitor.java:139)
	at org.everit.json.schema.ReferenceSchema.accept(ReferenceSchema.java:168)
	at org.everit.json.schema.Visitor.visit(Visitor.java:48)
	at org.everit.json.schema.ValidatingVisitor.visit(ValidatingVisitor.java:59)
	at org.everit.json.schema.ValidatingVisitor.lambda$getFailureOfSchema$2(ValidatingVisitor.java:199)
	at org.everit.json.schema.ValidationFailureReporter.inContextOfSchema(ValidationFailureReporter.java:34)
	at org.everit.json.schema.CollectingFailureReporter.inContextOfSchema(CollectingFailureReporter.java:25)
	at org.everit.json.schema.ValidatingVisitor.getFailureOfSchema(ValidatingVisitor.java:199)
	at org.everit.json.schema.ValidatingVisitor.visitCombinedSchema(ValidatingVisitor.java:164)
	at org.everit.json.schema.CombinedSchema.accept(CombinedSchema.java:200)
	at org.everit.json.schema.Visitor.visit(Visitor.java:48)
	at org.everit.json.schema.ValidatingVisitor.visit(ValidatingVisitor.java:59)
	at org.everit.json.schema.ValidatingVisitor.lambda$getFailureOfSchema$2(ValidatingVisitor.java:199)
	at org.everit.json.schema.ValidationFailureReporter.inContextOfSchema(ValidationFailureReporter.java:34)
	at org.everit.json.schema.CollectingFailureReporter.inContextOfSchema(CollectingFailureReporter.java:25)
	at org.everit.json.schema.ValidatingVisitor.getFailureOfSchema(ValidatingVisitor.java:199)
	at org.everit.json.schema.ValidatingVisitor.visitReferenceSchema(ValidatingVisitor.java:139)
	at org.everit.json.schema.ReferenceSchema.accept(ReferenceSchema.java:168)
	at org.everit.json.schema.Visitor.visit(Visitor.java:48)

lib version: 1.14.1

erosb commented

Hi! As a quick workaround I suggest using "$ref": "#".

My original schema is a very large schema, it will refer to another schema by allOf and $ref, and for browser viewing reason, we add $id(as absolute-URI) field on sub-schema.

My workaournd is remove $id fiield after parse it to json object since I only use it to valid data,

IMO, $id property here should not be visited since in spec