Fix unbounded allocations when reading untrusted binary data

This commit is contained in:
世界
2026-08-10 13:26:42 +08:00
parent 45ca32dcb9
commit f260e771ea
11 changed files with 151 additions and 90 deletions
+21 -12
View File
@@ -4,6 +4,7 @@ import (
"bufio"
"encoding/binary"
"io"
"math"
"os"
"sync"
"sync/atomic"
@@ -62,10 +63,9 @@ func (r *Reader) readMetadata() error {
if err != nil {
return err
}
keys := make([]string, entryLength)
domainIndex := make(map[string]int)
domainLength := make(map[string]int)
for i := 0; i < int(entryLength); i++ {
for range entryLength {
var (
code string
codeIndex uint64
@@ -75,7 +75,6 @@ func (r *Reader) readMetadata() error {
if err != nil {
return err
}
keys[i] = code
codeIndex, err = binary.ReadUvarint(reader)
if err != nil {
return err
@@ -84,6 +83,9 @@ func (r *Reader) readMetadata() error {
if err != nil {
return err
}
if codeIndex > math.MaxInt32 || codeLength > math.MaxInt32 {
return E.New("invalid metadata entry: ", code)
}
domainIndex[code] = int(codeIndex)
domainLength[code] = int(codeLength)
}
@@ -107,17 +109,22 @@ func (r *Reader) Read(code string) ([]Item, error) {
return nil, err
}
r.bufferedReader.Reset(r.reader)
itemList := make([]Item, r.domainLength[code])
for i := range itemList {
typeByte, err := r.bufferedReader.ReadByte()
length := r.domainLength[code]
var itemList []Item
for range length {
var (
typeByte byte
value string
)
typeByte, err = r.bufferedReader.ReadByte()
if err != nil {
return nil, err
}
itemList[i].Type = ItemType(typeByte)
itemList[i].Value, err = readString(r.bufferedReader)
value, err = readString(r.bufferedReader)
if err != nil {
return nil, err
}
itemList = append(itemList, Item{Type: ItemType(typeByte), Value: value})
}
return itemList, nil
}
@@ -144,12 +151,14 @@ func readString(reader io.ByteReader) (string, error) {
if err != nil {
return "", err
}
bytes := make([]byte, length)
for i := range bytes {
bytes[i], err = reader.ReadByte()
var result []byte
for range length {
var value byte
value, err = reader.ReadByte()
if err != nil {
return "", err
}
result = append(result, value)
}
return string(bytes), nil
return string(result), nil
}