diff --git a/compiler.go b/compiler.go index 3a34112..3610ca3 100644 --- a/compiler.go +++ b/compiler.go @@ -212,6 +212,7 @@ func (c *Compiler) findResource(url string) (*resource, error) { id, err := r.draft.resolveID(r.url, r.doc) if err != nil { + r.draft = nil return nil, err } if id != "" { @@ -219,6 +220,8 @@ func (c *Compiler) findResource(url string) (*resource, error) { } if err := r.fillSubschemas(c, r); err != nil { + r.draft = nil + r.subresources = nil return nil, err } @@ -258,6 +261,7 @@ func (c *Compiler) compileRef(r *resource, stack []schemaRef, refPtr string, res if r.schema == nil { r.schema = newSchema(r.url, r.floc, r.draft, r.doc) if _, err := c.compile(r, nil, schemaRef{"#", r.schema, false}, r); err != nil { + r.schema = nil return nil, err } } @@ -278,7 +282,11 @@ func (c *Compiler) compileRef(r *resource, stack []schemaRef, refPtr string, res } sr.schema = newSchema(r.url, sr.floc, r.draft, sr.doc) - return c.compile(r, stack, schemaRef{refPtr, sr.schema, false}, sr) + sch, err := c.compile(r, stack, schemaRef{refPtr, sr.schema, false}, sr) + if err != nil { + sr.schema = nil + } + return sch, err } func (c *Compiler) compileDynamicAnchors(r *resource, res *resource) error { diff --git a/schema_test.go b/schema_test.go index eabb1c4..b37546f 100644 --- a/schema_test.go +++ b/schema_test.go @@ -723,3 +723,62 @@ func decodeReader(t *testing.T, r io.Reader) interface{} { } return doc } + +func Test_CompileTwice_Direct(t *testing.T) { + c := jsonschema.NewCompiler() + invalidSchema := `{"type": "abcd"}` + if err := c.AddResource("schema.json", strings.NewReader(invalidSchema)); err != nil { + t.Fatal("failed to add resource: ", err) + } + _, err := c.Compile("schema.json") + if err == nil { + t.Fatal("schema compilation must fail") + } + _, err = c.Compile("schema.json") + if err == nil { + t.Fatal("schema compilation must fail second time") + } +} + +func Test_CompileTwice_Indirect1(t *testing.T) { + c := jsonschema.NewCompiler() + schema := `{"$ref": "invalid.json"}` + invalidSchema := `{"type": "abcd"}` + if err := c.AddResource("invalid.json", strings.NewReader(invalidSchema)); err != nil { + t.Fatal("failed to add resource: ", err) + } + if err := c.AddResource("schema.json", strings.NewReader(schema)); err != nil { + t.Fatal("failed to add resource: ", err) + } + _, err := c.Compile("schema.json") + if err == nil { + t.Fatal("schema compilation must fail") + } + _, err = c.Compile("schema.json") + if err == nil { + t.Fatal("schema compilation must fail second time") + } +} + +func Test_CompileTwice_Indirect2(t *testing.T) { + c := jsonschema.NewCompiler() + schema := `{"$ref": "invalid.json"}` + invalidSchema := `{"type": "abcd"}` + if err := c.AddResource("invalid.json", strings.NewReader(invalidSchema)); err != nil { + t.Fatal("failed to add resource: ", err) + } + if err := c.AddResource("schema1.json", strings.NewReader(schema)); err != nil { + t.Fatal("failed to add resource: ", err) + } + if err := c.AddResource("schema2.json", strings.NewReader(schema)); err != nil { + t.Fatal("failed to add resource: ", err) + } + _, err := c.Compile("schema1.json") + if err == nil { + t.Fatal("schema compilation must fail") + } + _, err = c.Compile("schema2.json") + if err == nil { + t.Fatal("schema compilation must fail second time") + } +}