Skip to content

Commit 99a442a

Browse files
committed
Read transaction fields incrementally and encode sortable ints safely
1 parent 26647e3 commit 99a442a

2 files changed

Lines changed: 22 additions & 13 deletions

File tree

kv/txn_codec.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -215,12 +215,7 @@ func readTxnField(r *bytes.Reader, n uint64, truncatedMessage string) ([]byte, e
215215
return nil, nil
216216
}
217217

218-
// Ensure the requested length does not exceed the remaining reader length.
219-
if n > uint64(r.Len()) {
220-
return nil, errors.New(truncatedMessage)
221-
}
222-
223-
// Guard against uint64 -> int overflow / excessively large allocations.
218+
// Guard against excessively large fields before attempting to read them.
224219
if n > uint64(math.MaxInt) {
225220
return nil, errors.New("transaction field size overflows int")
226221
}
@@ -240,12 +235,23 @@ func readTxnSizedBytes(r *bytes.Reader, n uint64) ([]byte, error) {
240235
return nil, nil
241236
}
242237

243-
// At this point, callers are expected to have validated that n is safe to
244-
// convert to int and does not exceed the remaining reader length.
245-
size := int(n)
246-
out := make([]byte, size)
247-
if _, err := io.ReadFull(r, out); err != nil {
248-
return nil, errors.WithStack(err)
238+
var out []byte
239+
var chunkBuf [txnReadChunkSize]byte
240+
remaining := n
241+
for remaining >= txnReadChunkSize {
242+
if _, err := io.ReadFull(r, chunkBuf[:]); err != nil {
243+
return nil, errors.WithStack(err)
244+
}
245+
out = append(out, chunkBuf[:]...)
246+
remaining -= txnReadChunkSize
247+
}
248+
for remaining > 0 {
249+
b, err := r.ReadByte()
250+
if err != nil {
251+
return nil, errors.WithStack(err)
252+
}
253+
out = append(out, b)
254+
remaining--
249255
}
250256
return out, nil
251257
}

store/list_helpers.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ func encodeSortableInt64(dst []byte, seq int64) {
8787
if len(dst) < sortableInt64Bytes {
8888
return
8989
}
90-
binary.BigEndian.PutUint64(dst, uint64(seq^math.MinInt64))
90+
buf := bytes.NewBuffer(dst[:0])
91+
// binary.Write cannot fail here: the payload is a fixed-size int64 and the
92+
// destination is an in-memory bytes.Buffer.
93+
_ = binary.Write(buf, binary.BigEndian, seq^math.MinInt64)
9194
}
9295

9396
// IsListMetaKey Exported helpers for other packages (e.g., Redis adapter).

0 commit comments

Comments
 (0)