diff --git a/internal/encoding/wire/wire.go b/internal/encoding/wire/wire.go index 033b4c0e..0706234a 100644 --- a/internal/encoding/wire/wire.go +++ b/internal/encoding/wire/wire.go @@ -9,9 +9,11 @@ package wire import ( "io" + "math" "math/bits" "github.com/golang/protobuf/v2/internal/errors" + "github.com/golang/protobuf/v2/internal/flags" ) // Number represents the field number. @@ -479,11 +481,17 @@ func SizeGroup(num Number, n int) int { // The Number is -1 if the decoded field number overflows. // Other than overflow, this does not check for field number validity. func DecodeTag(x uint64) (Number, Type) { - num := Number(x >> 3) - if num > MaxValidNumber { - num = -1 + // NOTE: MessageSet allows for larger field numbers than normal. + if flags.Proto1Legacy { + if x>>3 > uint64(math.MaxInt32) { + return -1, 0 + } + } else { + if x>>3 > uint64(MaxValidNumber) { + return -1, 0 + } } - return num, Type(x & 7) + return Number(x >> 3), Type(x & 7) } // EncodeTag encodes the field Number and wire Type into its unified form. diff --git a/internal/encoding/wire/wire_test.go b/internal/encoding/wire/wire_test.go index 01e4d346..f82a5269 100644 --- a/internal/encoding/wire/wire_test.go +++ b/internal/encoding/wire/wire_test.go @@ -136,8 +136,8 @@ func TestTag(t *testing.T) { wantRaw: dhex("f8ffffff0f"), consumeOps: ops{consumeTag{wantNum: MaxValidNumber, wantType: VarintType, wantCnt: 5}}, }, { - appendOps: ops{appendTag{inNum: MaxValidNumber + 1, inType: VarintType}}, - wantRaw: dhex("8080808010"), + appendOps: ops{appendVarint{inVal: ((math.MaxInt32+1)<<3 | uint64(VarintType))}}, + wantRaw: dhex("8080808040"), consumeOps: ops{consumeTag{wantErr: errFieldNumber}}, }}) }