From 65d557cbb014f297257287552c0cfa224cfc5deb Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Wed, 27 May 2026 11:29:01 -0700 Subject: [PATCH] fix(util): guard BytesToUint{16,32,64} against short input (#9713) * fix(util): guard BytesToUint{16,32,64} against short input length is computed as uint, so length-1 on an empty slice underflows to MaxUint and the loop indexes b[0] on a zero-length slice. BytesToUint16 also indexed b[0]/b[1] with no length check. All call sites today gate the slice length explicitly, so this hardens the API for new callers rather than fixing a live crash. Return 0 on short input, matching the existing variable-length contract. * BytesToUint16: match variable-length contract of the 32/64 helpers A 1-byte slice should return uint16(b[0]) rather than 0, matching how BytesToUint32 and BytesToUint64 treat short input. --- weed/util/bytes.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/weed/util/bytes.go b/weed/util/bytes.go index 43008c42f..4e9ce1d15 100644 --- a/weed/util/bytes.go +++ b/weed/util/bytes.go @@ -33,6 +33,9 @@ func BytesToHumanReadable(b uint64) string { func BytesToUint64(b []byte) (v uint64) { length := uint(len(b)) + if length == 0 { + return 0 + } for i := uint(0); i < length-1; i++ { v += uint64(b[i]) v <<= 8 @@ -42,6 +45,9 @@ func BytesToUint64(b []byte) (v uint64) { } func BytesToUint32(b []byte) (v uint32) { length := uint(len(b)) + if length == 0 { + return 0 + } for i := uint(0); i < length-1; i++ { v += uint32(b[i]) v <<= 8 @@ -50,9 +56,15 @@ func BytesToUint32(b []byte) (v uint32) { return } func BytesToUint16(b []byte) (v uint16) { - v += uint16(b[0]) - v <<= 8 - v += uint16(b[1]) + length := uint(len(b)) + if length == 0 { + return 0 + } + for i := uint(0); i < length-1; i++ { + v += uint16(b[i]) + v <<= 8 + } + v += uint16(b[length-1]) return } func Uint64toBytes(b []byte, v uint64) {