From e6bbcb3fc2c1fd1202a70f8cac533fe2b67a8435 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 4 Sep 2026 10:39:50 +0200 Subject: [PATCH] schema: guard schemaCache map with mutex to fix data race Load writes the package-level schemaCache map while Validate reads it via schemaForType. If Load runs concurrently with request validation (or is called twice concurrently), this is a concurrent map read/write race. Guard access with a sync.RWMutex so writes in Load and reads in schemaForType are properly serialized. --- controller/schema/schema.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/controller/schema/schema.go b/controller/schema/schema.go index d1475b73a..df2eb2ce6 100755 --- a/controller/schema/schema.go +++ b/controller/schema/schema.go @@ -9,14 +9,21 @@ import ( "path/filepath" "reflect" "strings" + "sync" "github.com/cupcake/jsonschema" ct "github.com/flynn/flynn/controller/types" ) -var schemaCache map[string]*jsonschema.Schema +var ( + schemaCacheMu sync.RWMutex + schemaCache map[string]*jsonschema.Schema +) func Load(schemaRoot string) error { + schemaCacheMu.Lock() + defer schemaCacheMu.Unlock() + if schemaCache != nil { return nil } @@ -53,6 +60,9 @@ func Load(schemaRoot string) error { } func schemaForType(thing interface{}) *jsonschema.Schema { + schemaCacheMu.RLock() + defer schemaCacheMu.RUnlock() + name := strings.ToLower(reflect.Indirect(reflect.ValueOf(thing)).Type().Name()) if name == "newjob" { name = "new_job"