Skip to content

Commit

Permalink
bounds check when reading from the buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
Zariel committed May 2, 2015
1 parent f42867a commit 58d90fa
Showing 1 changed file with 41 additions and 6 deletions.
47 changes: 41 additions & 6 deletions frame.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"fmt"
"io"
"net"
"runtime"
"sync"
"time"
)
Expand Down Expand Up @@ -371,12 +372,10 @@ func (f *framer) parseFrame() (frame frame, err error) {

defer func() {
if r := recover(); r != nil {
if perr, ok := r.(error); ok {
err = perr
return
if _, ok := r.(runtime.Error); ok {
panic(r)
}

panic(r)
err = r.(error)
}
}()

Expand Down Expand Up @@ -1161,18 +1160,28 @@ func (f *framer) readByte() byte {
}

func (f *framer) readInt() (n int) {
if len(f.rbuf) < 4 {
panic(fmt.Errorf("not enough bytes in buffer to read int require 4 got: %d", len(f.rbuf)))
}

n = int(int32(f.rbuf[0])<<24 | int32(f.rbuf[1])<<16 | int32(f.rbuf[2])<<8 | int32(f.rbuf[3]))
f.rbuf = f.rbuf[4:]
return
}

func (f *framer) readShort() (n uint16) {
if len(f.rbuf) < 2 {
panic(fmt.Errorf("not enough bytes in buffer to read short require 2 got: %d", len(f.rbuf)))
}
n = uint16(f.rbuf[0])<<8 | uint16(f.rbuf[1])
f.rbuf = f.rbuf[2:]
return
}

func (f *framer) readLong() (n int64) {
if len(f.rbuf) < 8 {
panic(fmt.Errorf("not enough bytes in buffer to read long require 8 got: %d", len(f.rbuf)))
}
n = int64(f.rbuf[0])<<56 | int64(f.rbuf[1])<<48 | int64(f.rbuf[2])<<40 | int64(f.rbuf[3])<<32 |
int64(f.rbuf[4])<<24 | int64(f.rbuf[5])<<16 | int64(f.rbuf[6])<<8 | int64(f.rbuf[7])
f.rbuf = f.rbuf[8:]
Expand All @@ -1181,19 +1190,33 @@ func (f *framer) readLong() (n int64) {

func (f *framer) readString() (s string) {
size := f.readShort()

if len(f.rbuf) < int(size) {
panic(fmt.Errorf("not enough bytes in buffer to read string require %d got: %d", size, len(f.rbuf)))
}

s = string(f.rbuf[:size])
f.rbuf = f.rbuf[size:]
return
}

func (f *framer) readLongString() (s string) {
size := f.readInt()

if len(f.rbuf) < size {
panic(fmt.Errorf("not enough bytes in buffer to read long string require %d got: %d", size, len(f.rbuf)))
}

s = string(f.rbuf[:size])
f.rbuf = f.rbuf[size:]
return
}

func (f *framer) readUUID() *UUID {
if len(f.rbuf) < 16 {
panic(fmt.Errorf("not enough bytes in buffer to read uuid require %d got: %d", 16, len(f.rbuf)))
}

// TODO: how to handle this error, if it is a uuid, then sureley, problems?
u, _ := UUIDFromBytes(f.rbuf[:16])
f.rbuf = f.rbuf[16:]
Expand All @@ -1217,6 +1240,10 @@ func (f *framer) readBytes() []byte {
return nil
}

if len(f.rbuf) < size {
panic(fmt.Errorf("not enough bytes in buffer to read bytes require %d got: %d", size, len(f.rbuf)))
}

// we cant make assumptions about the length of the life of the supplied byte
// slice so we defensivly copy it out of the underlying buffer. This has the
// downside of increasing allocs per read but will provide much greater memory
Expand All @@ -1240,11 +1267,19 @@ func (f *framer) readShortBytes() []byte {
}

func (f *framer) readInet() (net.IP, int) {
if len(f.rbuf) < 1 {
panic(fmt.Errorf("not enough bytes in buffer to read inet size require %d got: %d", 1, len(f.rbuf)))
}

size := f.rbuf[0]
f.rbuf = f.rbuf[1:]

if !(size == 4 || size == 16) {
panic(fmt.Sprintf("invalid IP size: %d", size))
panic(fmt.Errorf("invalid IP size: %d", size))
}

if len(f.rbuf) < 1 {
panic(fmt.Errorf("not enough bytes in buffer to read inet require %d got: %d", size, len(f.rbuf)))
}

ip := make([]byte, size)
Expand Down

0 comments on commit 58d90fa

Please sign in to comment.