Compare commits

...
Author SHA1 Message Date
dependabot[bot] 20a5c6c0b6 build(deps): bump github.com/shamaton/msgpack/v2 from 2.4.1 to 2.4.2
Bumps [github.com/shamaton/msgpack/v2](https://github.com/shamaton/msgpack) from 2.4.1 to 2.4.2.
- [Release notes](https://github.com/shamaton/msgpack/releases)
- [Changelog](https://github.com/shamaton/msgpack/blob/v2.4.2/CHANGELOG.md)
- [Commits](https://github.com/shamaton/msgpack/compare/v2.4.1...v2.4.2)

---
updated-dependencies:
- dependency-name: github.com/shamaton/msgpack/v2
  dependency-version: 2.4.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-08 08:22:58 +00:00
14 changed files with 337 additions and 118 deletions

No files matched your search

+1 -1
View File
@@ -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
+2 -2
View File
@@ -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=
+9
View File
@@ -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
+14 -7
View File
@@ -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)
}
@@ -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()
+4 -1
View File
@@ -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 {
+101
View File
@@ -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)
}
@@ -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 {
+39 -39
View File
@@ -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 {
+84 -13
View File
@@ -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 <= 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
if n < 0 {
return emptyBytes, fmt.Errorf("invalid declared byte length %d", n)
}
if _, err := d.r.Read(b); err != nil {
return emptyBytes, err
if n <= len(d.buf.Data) {
b := d.buf.Data[:n]
if err := d.readFull(b); err != nil {
return emptyBytes, err
}
return b, nil
}
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
}
+43 -43
View File
@@ -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
+1 -1
View File
@@ -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
}
+28 -5
View File
@@ -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
+1 -1
View File
@@ -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