fix(bsr): check nanosecond range during decoding (#3496)

pull/3498/head
Irena Rindos 3 years ago committed by GitHub
parent f59b6364f2
commit dcdb257b93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -41,4 +41,7 @@ var (
// ErrChecksum indicates that a checksum did not match.
ErrChecksum = errors.New("computed checksum did NOT match")
// ErrTimestampDecode indicates an error decoding a timestamp
ErrTimestampDecode = errors.New("error decoding timestamp")
)

@ -12,6 +12,8 @@ import (
const (
secondSize = 8
nanosecondSize = 4
// Values over 999999999 are 1 second and over
nanosecondLimit = 999999999
timestampSize = secondSize + nanosecondSize
)
@ -52,6 +54,9 @@ func decodeTimestamp(data []byte) (*Timestamp, error) {
seconds, data = binary.BigEndian.Uint64(data[:secondSize]), data[secondSize:]
nanoseconds, data = binary.BigEndian.Uint32(data[:nanosecondSize]), data[nanosecondSize:]
if nanoseconds > nanosecondLimit {
return nil, fmt.Errorf("%s: nanosecond value of %d exceeds the max nanosecond value of %d: %w", op, nanoseconds, nanosecondLimit, ErrTimestampDecode)
}
if len(data) != 0 {
return nil, fmt.Errorf("%s: extra data", op)
}

@ -0,0 +1,62 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package bsr
import (
"encoding/binary"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_DecodeTimestamp(t *testing.T) {
cases := []struct {
name string
nanos uint32
wantNanos int
wantErr bool
wantErrContains string
}{
{
name: "valid case 1",
nanos: uint32(999999999),
wantNanos: 999999999,
},
{
name: "valid case 2",
nanos: uint32(5),
wantNanos: 5,
},
{
name: "nanosecond overflow case 1",
nanos: uint32(1000000000),
wantErr: true,
wantErrContains: "bsr.decodeTimestamp: nanosecond value of 1000000000 exceeds the max nanosecond value of 999999999: error decoding timestamp",
},
{
name: "nanosecond overflow case 2",
nanos: uint32(2000000000),
wantErr: true,
wantErrContains: "bsr.decodeTimestamp: nanosecond value of 2000000000 exceeds the max nanosecond value of 999999999: error decoding timestamp",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
data := make([]byte, timestampSize)
seconds := uint64(0)
binary.BigEndian.PutUint64(data[:secondSize], seconds)
binary.BigEndian.PutUint32(data[secondSize:], tc.nanos)
got, err := decodeTimestamp(data)
if tc.wantErr {
require.Error(t, err)
assert.EqualError(t, err, tc.wantErrContains)
return
}
require.NoError(t, err)
require.Equal(t, tc.wantNanos, got.AsTime().Nanosecond())
})
}
}
Loading…
Cancel
Save