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.
This commit is contained in:
Chris Lu
2026-05-27 11:29:01 -07:00
committed by GitHub
parent d00acded8a
commit 65d557cbb0

View File

@@ -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) {