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
This commit is contained in:
Emmanuel T Odeke 2022-07-27 13:10:32 -06:00 committed by GitHub
parent 37e765daa6
commit 2f4faa58c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 3 deletions

View File

@ -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

View File

@ -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:

View File

@ -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