diff --git a/go.mod b/go.mod index cafdad8fc5..b0d738ebbd 100644 --- a/go.mod +++ b/go.mod @@ -75,7 +75,7 @@ require ( github.com/rogpeppe/go-internal v1.16.0 github.com/rs/cors v1.11.1 github.com/rs/zerolog v1.35.1 - github.com/shamaton/msgpack/v2 v2.4.1 + github.com/shamaton/msgpack/v2 v2.4.2 github.com/sirupsen/logrus v1.10.1 github.com/spf13/afero v1.15.0 github.com/spf13/cobra v1.10.2 diff --git a/go.sum b/go.sum index 16a7ef0c0a..de57b0472e 100644 --- a/go.sum +++ b/go.sum @@ -1102,8 +1102,8 @@ github.com/sethvargo/go-diceware v0.6.0 h1:B3nhMhbBP7KwtTQ7hHRIOmv5FqeD8bJs77RFr github.com/sethvargo/go-diceware v0.6.0/go.mod h1:lHmdB0xuWaJ06KCraW6bztRT+71Dp+lsXQvborhhsBc= github.com/sethvargo/go-password v0.4.0 h1:eSidVKQw5C7CmTDAtH3RipBTSjdU1ZRxQaynD2GWLVU= github.com/sethvargo/go-password v0.4.0/go.mod h1:PO3nYHwUpcHPR0F9woy7a4abZPvzRuqJr0GaeIYTm3k= -github.com/shamaton/msgpack/v2 v2.4.1 h1:JtJ141QoQ3NqgPDsjq2v9VXlaON8SiQOwEaoNLEK/MQ= -github.com/shamaton/msgpack/v2 v2.4.1/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI= +github.com/shamaton/msgpack/v2 v2.4.2 h1:ukiqiwF8rIb8EG6hD8iPha3g85AC7EdCxFyobDj6oHk= +github.com/shamaton/msgpack/v2 v2.4.2/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v4 v4.26.6 h1:Mzr/npDtQC/xpeEuQKHZt8Zo9CmPvhTj8nkR8w5TLDs= diff --git a/vendor/github.com/shamaton/msgpack/v2/CHANGELOG.md b/vendor/github.com/shamaton/msgpack/v2/CHANGELOG.md new file mode 100644 index 0000000000..7a56441832 --- /dev/null +++ b/vendor/github.com/shamaton/msgpack/v2/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## [v2.4.2](https://github.com/shamaton/msgpack/compare/v2.4.1...v2.4.2) - 2026-08-30 +- fix: bound streaming decoder allocations against declared lengths (v2) by @shamaton in https://github.com/shamaton/msgpack/pull/115 + +## [v2.4.1](https://github.com/shamaton/msgpack/commits/v2.4.1) - 2026-05-14 +- fix: backport ext frame bounds validation to v2 by @shamaton in https://github.com/shamaton/msgpack/pull/66 +- Add tagpr configuration for v2 by @shamaton in https://github.com/shamaton/msgpack/pull/67 +- Format v2 branch files by @shamaton in https://github.com/shamaton/msgpack/pull/69 diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/bin.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/bin.go index 48a6f3b33d..157353ab55 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/bin.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/bin.go @@ -39,8 +39,12 @@ func (d *decoder) asBinWithCode(code byte, k reflect.Kind) ([]byte, error) { if err != nil { return emptyBytes, err } + l, err := lengthFromUint32(binary.BigEndian.Uint32(bs)) + if err != nil { + return emptyBytes, err + } // avoid common buffer reference - return d.copySizeN(int(binary.BigEndian.Uint32(bs))) + return d.copySizeN(l) } return emptyBytes, d.errorTemplate(code, k) @@ -52,11 +56,14 @@ func (d *decoder) asBinStringWithCode(code byte, k reflect.Kind) (string, error) } func (d *decoder) copySizeN(n int) ([]byte, error) { - bs, err := d.readSizeN(n) - if err != nil { - return emptyBytes, err + if n <= len(d.buf.Data) { + bs, err := d.readSizeN(n) + if err != nil { + return emptyBytes, err + } + v := make([]byte, n) + copy(v, bs) + return v, nil } - v := make([]byte, n) - copy(v, bs) - return v, nil + return d.readSizeN(n) } diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/decoding.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/decoding.go index 1afbe525af..e05a0af377 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/decoding.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/decoding.go @@ -145,8 +145,9 @@ func (d *decoder) decodeWithCode(code byte, rv reflect.Value) error { } // create slice dynamically - tmpSlice := reflect.MakeSlice(rv.Type(), l, l) + tmpSlice := reflect.MakeSlice(rv.Type(), 0, initialSliceCap(l, rv.Type().Elem())) for i := 0; i < l; i++ { + tmpSlice = reflect.Append(tmpSlice, reflect.Zero(rv.Type().Elem())) v := tmpSlice.Index(i) if v.Kind() == reflect.Struct { structCode, err := d.readSize1() @@ -259,7 +260,7 @@ func (d *decoder) decodeWithCode(code byte, rv reflect.Value) error { key := rv.Type().Key() value := rv.Type().Elem() if rv.IsNil() { - rv.Set(reflect.MakeMapWithSize(rv.Type(), l)) + rv.Set(reflect.MakeMapWithSize(rv.Type(), initialMapCapForType(l, key, value))) } for i := 0; i < l; i++ { k := reflect.New(key).Elem() diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/ext.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/ext.go index 4e1885bcad..cab597e284 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/ext.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/ext.go @@ -146,7 +146,10 @@ func (d *decoder) readIfExtType(code byte) (innerType int8, data []byte, err err if err != nil { return 0, nil, err } - size := int(binary.BigEndian.Uint32(bs)) + size, err := lengthFromUint32(binary.BigEndian.Uint32(bs)) + if err != nil { + return 0, nil, err + } typ, err := d.readSize1() if err != nil { diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/guard.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/guard.go new file mode 100644 index 0000000000..a85521daea --- /dev/null +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/guard.go @@ -0,0 +1,101 @@ +package decoding + +import ( + "errors" + "fmt" + "math" + "reflect" +) + +const ( + // maxPreallocBytes bounds the initial allocation made from an + // attacker-declared byte length (Bin/Str/Ext payloads) before any + // payload byte has been read. Larger declared lengths are read + // incrementally and grown only as bytes actually arrive. + maxPreallocBytes = 256 << 10 // 256 KiB + + // maxPreallocMapSize bounds the entry hint used to pre-size a map + // from an attacker-declared pair count before any pair is decoded. + maxPreallocMapSize = 8192 +) + +// errDeclaredLengthTooLarge is returned when a declared 32-bit length cannot +// be represented as a non-negative int (32-bit platforms). +var errDeclaredLengthTooLarge = errors.New("declared length is too large") + +// lengthFromUint32 converts a MessagePack-declared 32-bit length to int, +// rejecting values that are not representable as a non-negative int. +func lengthFromUint32(u uint32) (int, error) { + if int64(u) > int64(math.MaxInt) { + return 0, fmt.Errorf("%w: %d", errDeclaredLengthTooLarge, u) + } + return int(u), nil // #nosec G115 -- checked above +} + +// initialByteCap returns the capacity to reserve for a declared byte length +// before its payload has been read. +func initialByteCap(n int) int { + if n < 1 { + return 0 + } + if n < maxPreallocBytes { + return n + } + return maxPreallocBytes +} + +// initialSliceCap returns the element capacity to reserve for a declared +// slice length, capped both by the declared count and by a byte budget so +// large element types never over-commit. +func initialSliceCap(l int, elemType reflect.Type) int { + if l < 1 { + return 0 + } + elemSize := elemType.Size() + if elemSize < 1 { + elemSize = 1 + } + budget := maxPreallocBytes / int(elemSize) + if budget < 1 { + budget = 1 + } + if l < budget { + return l + } + return budget +} + +// initialMapCap returns the entry hint used to pre-size a map from a +// declared pair count. +func initialMapCap(l int) int { + if l < 1 { + return 0 + } + if l < maxPreallocMapSize { + return l + } + return maxPreallocMapSize +} + +// initialMapCapForType is initialMapCap for maps created dynamically via +// reflection, where the key/value types are only known at decode time and +// can be arbitrarily large structs. It additionally bounds the hint by a +// byte budget derived from the key/value sizes so a declared pair count +// can't force a multi-megabyte allocation before any pair has been decoded. +func initialMapCapForType(l int, key, value reflect.Type) int { + if l < 1 { + return 0 + } + entrySize := key.Size() + value.Size() + if entrySize < 1 { + entrySize = 1 + } + budget := maxPreallocBytes / int(entrySize) + if budget < 1 { + budget = 1 + } + if l < budget { + return initialMapCap(l) + } + return initialMapCap(budget) +} diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/interface.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/interface.go index d2202149cd..5b8a838781 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/interface.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/interface.go @@ -15,6 +15,10 @@ func (d *decoder) asInterface(k reflect.Kind) (interface{}, error) { return d.asInterfaceWithCode(code, k) } +// typeInterfaceValue is the reflect.Type of interface{}; used to size the +// element budget when pre-allocating []interface{}. +var typeInterfaceValue = reflect.TypeOf((*interface{})(nil)).Elem() + func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interface{}, error) { switch { case code == def.Nil: @@ -110,13 +114,13 @@ func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interface{}, e return nil, err } - v := make([]interface{}, l) + v := make([]interface{}, 0, initialSliceCap(l, typeInterfaceValue)) for i := 0; i < l; i++ { vv, err := d.asInterface(k) if err != nil { return nil, err } - v[i] = vv + v = append(v, vv) } return v, nil @@ -126,7 +130,7 @@ func (d *decoder) asInterfaceWithCode(code byte, k reflect.Kind) (interface{}, e return nil, err } - v := make(map[interface{}]interface{}, l) + v := make(map[interface{}]interface{}, initialMapCap(l)) for i := 0; i < l; i++ { keyCode, err := d.readSize1() if err != nil { diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/map.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/map.go index 3af27d687f..7340a21c7e 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/map.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/map.go @@ -73,7 +73,7 @@ func (d *decoder) mapLength(code byte, k reflect.Kind) (int, error) { if err != nil { return 0, err } - return int(binary.BigEndian.Uint32(bs)), nil + return lengthFromUint32(binary.BigEndian.Uint32(bs)) } return 0, d.errorTemplate(code, k) @@ -87,7 +87,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { switch t { case typeMapStringInt: - m := make(map[string]int, l) + m := make(map[string]int, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -103,7 +103,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringUint: - m := make(map[string]uint, l) + m := make(map[string]uint, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -119,7 +119,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringFloat32: - m := make(map[string]float32, l) + m := make(map[string]float32, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -135,7 +135,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringFloat64: - m := make(map[string]float64, l) + m := make(map[string]float64, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -151,7 +151,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringBool: - m := make(map[string]bool, l) + m := make(map[string]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -167,7 +167,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringString: - m := make(map[string]string, l) + m := make(map[string]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -183,7 +183,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringInt8: - m := make(map[string]int8, l) + m := make(map[string]int8, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -199,7 +199,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringInt16: - m := make(map[string]int16, l) + m := make(map[string]int16, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -215,7 +215,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringInt32: - m := make(map[string]int32, l) + m := make(map[string]int32, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -231,7 +231,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringInt64: - m := make(map[string]int64, l) + m := make(map[string]int64, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -247,7 +247,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringUint8: - m := make(map[string]uint8, l) + m := make(map[string]uint8, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -262,7 +262,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { rv.Set(reflect.ValueOf(m)) return true, nil case typeMapStringUint16: - m := make(map[string]uint16, l) + m := make(map[string]uint16, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -278,7 +278,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringUint32: - m := make(map[string]uint32, l) + m := make(map[string]uint32, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -294,7 +294,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapStringUint64: - m := make(map[string]uint64, l) + m := make(map[string]uint64, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asString(keyKind) if err != nil { @@ -310,7 +310,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapIntString: - m := make(map[int]string, l) + m := make(map[int]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -326,7 +326,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt8String: - m := make(map[int8]string, l) + m := make(map[int8]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -342,7 +342,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt16String: - m := make(map[int16]string, l) + m := make(map[int16]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -358,7 +358,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt32String: - m := make(map[int32]string, l) + m := make(map[int32]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -374,7 +374,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt64String: - m := make(map[int64]string, l) + m := make(map[int64]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -390,7 +390,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapIntBool: - m := make(map[int]bool, l) + m := make(map[int]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -406,7 +406,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt8Bool: - m := make(map[int8]bool, l) + m := make(map[int8]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -422,7 +422,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt16Bool: - m := make(map[int16]bool, l) + m := make(map[int16]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -438,7 +438,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt32Bool: - m := make(map[int32]bool, l) + m := make(map[int32]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -454,7 +454,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapInt64Bool: - m := make(map[int64]bool, l) + m := make(map[int64]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asInt(keyKind) if err != nil { @@ -470,7 +470,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUintString: - m := make(map[uint]string, l) + m := make(map[uint]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -486,7 +486,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint8String: - m := make(map[uint8]string, l) + m := make(map[uint8]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -502,7 +502,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint16String: - m := make(map[uint16]string, l) + m := make(map[uint16]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -518,7 +518,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint32String: - m := make(map[uint32]string, l) + m := make(map[uint32]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -534,7 +534,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint64String: - m := make(map[uint64]string, l) + m := make(map[uint64]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -550,7 +550,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUintBool: - m := make(map[uint]bool, l) + m := make(map[uint]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -566,7 +566,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint8Bool: - m := make(map[uint8]bool, l) + m := make(map[uint8]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -582,7 +582,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint16Bool: - m := make(map[uint16]bool, l) + m := make(map[uint16]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -598,7 +598,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint32Bool: - m := make(map[uint32]bool, l) + m := make(map[uint32]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -614,7 +614,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapUint64Bool: - m := make(map[uint64]bool, l) + m := make(map[uint64]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asUint(keyKind) if err != nil { @@ -630,7 +630,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapFloat32String: - m := make(map[float32]string, l) + m := make(map[float32]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asFloat32(keyKind) if err != nil { @@ -646,7 +646,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapFloat64String: - m := make(map[float64]string, l) + m := make(map[float64]string, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asFloat64(keyKind) if err != nil { @@ -662,7 +662,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapFloat32Bool: - m := make(map[float32]bool, l) + m := make(map[float32]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asFloat32(keyKind) if err != nil { @@ -678,7 +678,7 @@ func (d *decoder) asFixedMap(rv reflect.Value, l int) (bool, error) { return true, nil case typeMapFloat64Bool: - m := make(map[float64]bool, l) + m := make(map[float64]bool, initialMapCap(l)) for i := 0; i < l; i++ { k, err := d.asFloat64(keyKind) if err != nil { diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/read.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/read.go index d65c218027..46097d276f 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/read.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/read.go @@ -1,50 +1,121 @@ package decoding +import ( + "fmt" + "io" +) + +// readFull fills b completely from d.r. The common case, where the +// underlying reader already returns the full amount requested, completes +// with a single Read call. Readers that legitimately return fewer bytes than +// requested (n > 0, err == nil) fall back to looping over the remainder. +// Unlike io.ReadFull, an EOF reached only after some bytes were already +// consumed by this call is still reported as io.EOF, not io.ErrUnexpectedEOF, +// preserving this package's historical error values. +func (d *decoder) readFull(b []byte) error { + for len(b) > 0 { + n, err := d.r.Read(b) + if n < 0 || n > len(b) { + return io.ErrNoProgress + } + b = b[n:] + if len(b) == 0 { + return nil + } + if err != nil { + return err + } + if n == 0 { + return io.ErrNoProgress + } + } + return nil +} + func (d *decoder) readSize1() (byte, error) { - if _, err := d.r.Read(d.buf.B1); err != nil { + if err := d.readFull(d.buf.B1); err != nil { return 0, err } return d.buf.B1[0], nil } func (d *decoder) readSize2() ([]byte, error) { - if _, err := d.r.Read(d.buf.B2); err != nil { + if err := d.readFull(d.buf.B2); err != nil { return emptyBytes, err } return d.buf.B2, nil } func (d *decoder) readSize4() ([]byte, error) { - if _, err := d.r.Read(d.buf.B4); err != nil { + if err := d.readFull(d.buf.B4); err != nil { return emptyBytes, err } return d.buf.B4, nil } func (d *decoder) readSize8() ([]byte, error) { - if _, err := d.r.Read(d.buf.B8); err != nil { + if err := d.readFull(d.buf.B8); err != nil { return emptyBytes, err } return d.buf.B8, nil } func (d *decoder) readSize16() ([]byte, error) { - if _, err := d.r.Read(d.buf.B16); err != nil { + if err := d.readFull(d.buf.B16); err != nil { return emptyBytes, err } return d.buf.B16, nil } func (d *decoder) readSizeN(n int) ([]byte, error) { - var b []byte + if n < 0 { + return emptyBytes, fmt.Errorf("invalid declared byte length %d", n) + } if n <= len(d.buf.Data) { - b = d.buf.Data[:n] - } else { - d.buf.Data = append(d.buf.Data, make([]byte, n-len(d.buf.Data))...) - b = d.buf.Data + b := d.buf.Data[:n] + if err := d.readFull(b); err != nil { + return emptyBytes, err + } + return b, nil } - if _, err := d.r.Read(b); err != nil { - return emptyBytes, err + if n <= maxPreallocBytes { + b := make([]byte, n) + if err := d.readFull(b); err != nil { + return emptyBytes, err + } + return b, nil + } + return d.readSizeNGrowing(n) +} + +// readSizeNGrowing reads a declared byte length that exceeds maxPreallocBytes. +// Rather than accumulating fixed-size chunks with append (which pays for a +// separate chunk buffer plus a copy into the growing slice on every +// iteration), it doubles the output slice's own capacity and reads directly +// into the newly available space, halving the bytes copied for large, +// legitimate payloads. +func (d *decoder) readSizeNGrowing(n int) ([]byte, error) { + b := make([]byte, 0, initialByteCap(n)) + for len(b) < n { + if len(b) == cap(b) { + newCap := n + if remaining := n - cap(b); remaining > cap(b) { + newCap = cap(b) * 2 + } + grown := make([]byte, len(b), newCap) + copy(grown, b) + b = grown + } + + start := len(b) + end := cap(b) + if n < end { + end = n + } + b = b[:end] + if err := d.readFull(b[start:end]); err != nil { + return emptyBytes, err + } } return b, nil } diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/slice.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/slice.go index 98e81fb7da..9ad6dfd5b1 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/slice.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/slice.go @@ -47,7 +47,7 @@ func (d *decoder) sliceLength(code byte, k reflect.Kind) (int, error) { if err != nil { return 0, err } - return int(binary.BigEndian.Uint32(bs)), nil + return lengthFromUint32(binary.BigEndian.Uint32(bs)) } return 0, d.errorTemplate(code, k) } @@ -58,169 +58,169 @@ func (d *decoder) asFixedSlice(rv reflect.Value, l int) (bool, error) { switch t { case typeIntSlice: - sli := make([]int, l) - for i := range sli { + sli := make([]int, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asInt(k) if err != nil { return false, err } - sli[i] = int(v) + sli = append(sli, int(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeUintSlice: - sli := make([]uint, l) - for i := range sli { + sli := make([]uint, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asUint(k) if err != nil { return false, err } - sli[i] = uint(v) + sli = append(sli, uint(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeStringSlice: - sli := make([]string, l) - for i := range sli { + sli := make([]string, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asString(k) if err != nil { return false, err } - sli[i] = v + sli = append(sli, v) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeBoolSlice: - sli := make([]bool, l) - for i := range sli { + sli := make([]bool, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asBool(k) if err != nil { return false, err } - sli[i] = v + sli = append(sli, v) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeFloat32Slice: - sli := make([]float32, l) - for i := range sli { + sli := make([]float32, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asFloat32(k) if err != nil { return false, err } - sli[i] = v + sli = append(sli, v) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeFloat64Slice: - sli := make([]float64, l) - for i := range sli { + sli := make([]float64, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asFloat64(k) if err != nil { return false, err } - sli[i] = v + sli = append(sli, v) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeInt8Slice: - sli := make([]int8, l) - for i := range sli { + sli := make([]int8, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asInt(k) if err != nil { return false, err } - sli[i] = int8(v) + sli = append(sli, int8(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeInt16Slice: - sli := make([]int16, l) - for i := range sli { + sli := make([]int16, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asInt(k) if err != nil { return false, err } - sli[i] = int16(v) + sli = append(sli, int16(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeInt32Slice: - sli := make([]int32, l) - for i := range sli { + sli := make([]int32, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asInt(k) if err != nil { return false, err } - sli[i] = int32(v) + sli = append(sli, int32(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeInt64Slice: - sli := make([]int64, l) - for i := range sli { + sli := make([]int64, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asInt(k) if err != nil { return false, err } - sli[i] = v + sli = append(sli, v) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeUint8Slice: - sli := make([]uint8, l) - for i := range sli { + sli := make([]uint8, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asUint(k) if err != nil { return false, err } - sli[i] = uint8(v) + sli = append(sli, uint8(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeUint16Slice: - sli := make([]uint16, l) - for i := range sli { + sli := make([]uint16, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asUint(k) if err != nil { return false, err } - sli[i] = uint16(v) + sli = append(sli, uint16(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeUint32Slice: - sli := make([]uint32, l) - for i := range sli { + sli := make([]uint32, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asUint(k) if err != nil { return false, err } - sli[i] = uint32(v) + sli = append(sli, uint32(v)) } rv.Set(reflect.ValueOf(sli)) return true, nil case typeUint64Slice: - sli := make([]uint64, l) - for i := range sli { + sli := make([]uint64, 0, initialSliceCap(l, t.Elem())) + for i := 0; i < l; i++ { v, err := d.asUint(k) if err != nil { return false, err } - sli[i] = v + sli = append(sli, v) } rv.Set(reflect.ValueOf(sli)) return true, nil diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/string.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/string.go index d50d9f8309..17b86a3b07 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/string.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/string.go @@ -41,7 +41,7 @@ func (d *decoder) stringByteLength(code byte, k reflect.Kind) (int, error) { if err != nil { return 0, err } - return int(binary.BigEndian.Uint32(b)), nil + return lengthFromUint32(binary.BigEndian.Uint32(b)) } else if code == def.Nil { return 0, nil } diff --git a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/struct.go b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/struct.go index 1d60ed83df..b47e760c2d 100644 --- a/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/struct.go +++ b/vendor/github.com/shamaton/msgpack/v2/internal/stream/decoding/struct.go @@ -2,6 +2,7 @@ package decoding import ( "encoding/binary" + "math" "reflect" "sync" @@ -199,7 +200,11 @@ func (d *decoder) jumpOffset() error { if err != nil { return err } - _, err = d.readSizeN(int(binary.BigEndian.Uint32(bs))) + l, err := lengthFromUint32(binary.BigEndian.Uint32(bs)) + if err != nil { + return err + } + _, err = d.readSizeN(l) return err case d.isFixSlice(code): @@ -225,7 +230,10 @@ func (d *decoder) jumpOffset() error { if err != nil { return err } - l := int(binary.BigEndian.Uint32(bs)) + l, err := lengthFromUint32(binary.BigEndian.Uint32(bs)) + if err != nil { + return err + } for i := 0; i < l; i++ { if err = d.jumpOffset(); err != nil { return err @@ -255,8 +263,16 @@ func (d *decoder) jumpOffset() error { if err != nil { return err } - l := int(binary.BigEndian.Uint32(bs)) - for i := 0; i < l*2; i++ { + l, err := lengthFromUint32(binary.BigEndian.Uint32(bs)) + if err != nil { + return err + } + // skip key and value separately: multiplying the pair count would + // overflow on 32-bit platforms + for i := 0; i < l; i++ { + if err = d.jumpOffset(); err != nil { + return err + } if err = d.jumpOffset(); err != nil { return err } @@ -297,7 +313,14 @@ func (d *decoder) jumpOffset() error { if err != nil { return err } - _, err = d.readSizeN(def.Byte1 + int(binary.BigEndian.Uint32(bs))) + l, err := lengthFromUint32(binary.BigEndian.Uint32(bs)) + if err != nil { + return err + } + if l >= math.MaxInt { // Byte1 + l must not overflow + return errDeclaredLengthTooLarge + } + _, err = d.readSizeN(def.Byte1 + l) return err } return nil diff --git a/vendor/modules.txt b/vendor/modules.txt index 75f9ed5c47..e8175b2f57 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1961,7 +1961,7 @@ github.com/sethvargo/go-diceware/diceware # github.com/sethvargo/go-password v0.4.0 ## explicit; go 1.25 github.com/sethvargo/go-password/password -# github.com/shamaton/msgpack/v2 v2.4.1 +# github.com/shamaton/msgpack/v2 v2.4.2 ## explicit; go 1.20 github.com/shamaton/msgpack/v2 github.com/shamaton/msgpack/v2/def