Skip to content

Commit

Permalink
protocol/io: (Func)SliceOfLen: Use interface for checking if IO is …
Browse files Browse the repository at this point in the history
…reader.

Fixes an issue where multiprotocol implementations that return their own `*Reader` would lead to broken slice reading.
  • Loading branch information
Sandertv committed Dec 31, 2024
1 parent 5af8736 commit 9afea8b
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 28 deletions.
20 changes: 10 additions & 10 deletions minecraft/protocol/io.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,9 @@ const maxSliceLength = 1024

// SliceOfLen reads/writes the elements of a slice of type T with length l.
func SliceOfLen[T any, S ~*[]T, A PtrMarshaler[T]](r IO, l uint32, x S) {
rd, reader := r.(*Reader)
if reader {
if rd.limitsEnabled && l > maxSliceLength {
rd.panicf("slice length was too long: length of %v", l)
}
limit, ok := r.(sliceReader)
if ok {
limit.SliceLimit(l, maxSliceLength)
*x = make([]T, l)
}

Expand All @@ -158,11 +156,9 @@ func SliceOfLen[T any, S ~*[]T, A PtrMarshaler[T]](r IO, l uint32, x S) {

// FuncSliceOfLen reads/writes the elements of a slice of type T with length l using func f.
func FuncSliceOfLen[T any, S ~*[]T](r IO, l uint32, x S, f func(*T)) {
rd, reader := r.(*Reader)
if reader {
if rd.limitsEnabled && l > maxSliceLength {
rd.panicf("slice length was too long: length of %v", l)
}
limit, ok := r.(sliceReader)
if ok {
limit.SliceLimit(l, maxSliceLength)
*x = make([]T, l)
}

Expand All @@ -171,6 +167,10 @@ func FuncSliceOfLen[T any, S ~*[]T](r IO, l uint32, x S, f func(*T)) {
}
}

type sliceReader interface {
SliceLimit(value uint32, max uint32)
}

// FuncIOSliceOfLen reads/writes the elements of a slice of type T with length l using func f.
func FuncIOSliceOfLen[T any, S ~*[]T](r IO, l uint32, x S, f func(IO, *T)) {
FuncSliceOfLen(r, l, x, func(v *T) {
Expand Down
23 changes: 5 additions & 18 deletions minecraft/protocol/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,24 +611,11 @@ func (r *Reader) Bitset(x *Bitset, size int) {
r.panic(errBitsetOverflow)
}

// LimitUint32 checks if the value passed is lower than the limit passed. If not, the Reader panics.
func (r *Reader) LimitUint32(value uint32, max uint32) {
if max == math.MaxUint32 {
// Account for 0-1 overflowing into max.
max = 0
}
if value > max {
r.panicf("uint32 %v exceeds maximum of %v", value, max)
}
}

// LimitInt32 checks if the value passed is lower than the limit passed and higher than the minimum. If not,
// the Reader panics.
func (r *Reader) LimitInt32(value int32, min, max int32) {
if value < min {
r.panicf("int32 %v exceeds minimum of %v", value, min)
} else if value > max {
r.panicf("int32 %v exceeds maximum of %v", value, max)
// SliceLimit checks if the value passed is lower than the limit passed. If
// not, the Reader panics.
func (r *Reader) SliceLimit(value uint32, max uint32) {
if value > max && r.limitsEnabled {
r.panicf("slice length was too long: length of %v (max %v)", value, max)
}
}

Expand Down

0 comments on commit 9afea8b

Please sign in to comment.