From 2f4faa58c12412faa8a1c70e19563ef0fc291866 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Wed, 27 Jul 2022 13:10:32 -0600 Subject: [PATCH] fix: orm/*, store/*: fix non-determinism from map iteration (#12751) Reported by informalsystems/gosec's map iteration pass, this change fixes non-determinism from iterating with a map, whose definition in the Go spec guarantees that the order of keys and values presented during iteration will be randomized. Fixes #12428 Fixes #12430 Fixes #12431 --- orm/model/ormdb/json.go | 12 +++++++++++- store/v2alpha1/multi/migration.go | 12 +++++++++++- store/v2alpha1/multi/store.go | 9 ++++++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/orm/model/ormdb/json.go b/orm/model/ormdb/json.go index 3a64ae52fbe6..79a668ccd10d 100644 --- a/orm/model/ormdb/json.go +++ b/orm/model/ormdb/json.go @@ -15,7 +15,17 @@ import ( ) func (m moduleDB) DefaultJSON(target ormjson.WriteTarget) error { - for name, table := range m.tablesByName { + tableNames := make([]protoreflect.FullName, 0, len(m.tablesByName)) + for name := range m.tablesByName { + tableNames = append(tableNames, name) + } + sort.Slice(tableNames, func(i, j int) bool { + ti, tj := tableNames[i], tableNames[j] + return ti.Name() < tj.Name() + }) + + for _, name := range tableNames { + table := m.tablesByName[name] w, err := target.OpenWriter(name) if err != nil { return err diff --git a/store/v2alpha1/multi/migration.go b/store/v2alpha1/multi/migration.go index caaddbf45283..c1285de5989a 100644 --- a/store/v2alpha1/multi/migration.go +++ b/store/v2alpha1/multi/migration.go @@ -1,6 +1,8 @@ package multi import ( + "sort" + dbm "github.com/cosmos/cosmos-sdk/db" "github.com/cosmos/cosmos-sdk/store/iavl" "github.com/cosmos/cosmos-sdk/store/mem" @@ -16,8 +18,16 @@ func MigrateFromV1(rootMultiStore *v1Store.Store, store2db dbm.Connection, store *iavl.Store name string } + storeKeysByName := rootMultiStore.StoreKeysByName() + keys := make([]string, 0, len(storeKeysByName)) + for key := range storeKeysByName { + keys = append(keys, key) + } + sort.Strings(keys) + var stores []namedStore - for _, storeKey := range rootMultiStore.StoreKeysByName() { + for _, key := range keys { + storeKey := storeKeysByName[key] keyName := storeKey.Name() switch store := rootMultiStore.GetStoreByName(keyName).(type) { case *iavl.Store: diff --git a/store/v2alpha1/multi/store.go b/store/v2alpha1/multi/store.go index c39b8e0e854c..0913979f10f5 100644 --- a/store/v2alpha1/multi/store.go +++ b/store/v2alpha1/multi/store.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "math" + "sort" "strings" "sync" @@ -327,8 +328,14 @@ func NewStore(db dbm.Connection, opts StoreConfig) (ret *Store, err error) { if err != nil { return } + skeys := make([]string, 0, len(reg.StoreSchema)) + for skey := range reg.StoreSchema { + skeys = append(skeys, skey) + } + sort.Strings(skeys) // NB. the migrated contents and schema are not committed until the next store.Commit - for skey, typ := range reg.StoreSchema { + for _, skey := range skeys { + typ := reg.StoreSchema[skey] err = schemaWriter.Set([]byte(skey), []byte{byte(typ)}) if err != nil { return