From 1726b83dc419f59f5bd75bef4ae0278aab68283f Mon Sep 17 00:00:00 2001 From: Joe Tsai Date: Thu, 25 Jun 2020 10:40:16 -0700 Subject: [PATCH] internal/impl: introduce instability to protoreflect.Message.Range order Change-Id: I6f53aaf4071b4cbf596f3438a83cf3e5c93f1712 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/240017 Reviewed-by: Herbie Ong --- internal/detrand/rand.go | 8 ++++++++ internal/impl/message_reflect.go | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/internal/detrand/rand.go b/internal/detrand/rand.go index a904dd1f..49c8676d 100644 --- a/internal/detrand/rand.go +++ b/internal/detrand/rand.go @@ -26,6 +26,14 @@ func Bool() bool { return randSeed%2 == 1 } +// Intn returns a deterministically random integer between 0 and n-1, inclusive. +func Intn(n int) int { + if n <= 0 { + panic("must be positive") + } + return int(randSeed % uint64(n)) +} + // randSeed is a best-effort at an approximate hash of the Go binary. var randSeed = binaryHash() diff --git a/internal/impl/message_reflect.go b/internal/impl/message_reflect.go index 0f4b8db7..f0bb02fc 100644 --- a/internal/impl/message_reflect.go +++ b/internal/impl/message_reflect.go @@ -8,6 +8,7 @@ import ( "fmt" "reflect" + "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" ) @@ -92,6 +93,12 @@ func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) { i++ } } + + // Introduce instability to iteration order, but keep it deterministic. + if len(mi.rangeInfos) > 1 && detrand.Bool() { + i := detrand.Intn(len(mi.rangeInfos) - 1) + mi.rangeInfos[i], mi.rangeInfos[i+1] = mi.rangeInfos[i+1], mi.rangeInfos[i] + } } func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type, si structInfo) {