Do more boundary checks in block decoding.

This commit is contained in:
Sascha L. Teichmann 2015-08-24 10:45:28 +02:00
parent 011cd0e4f4
commit 08031f1dcd
1 changed files with 33 additions and 4 deletions

View File

@ -19,6 +19,7 @@ import (
var (
ErrNoMoreBlocks = errors.New("No more blocks.")
ErrMapContentSizeMismatch = errors.New("Content size does not match.")
ErrBlockTruncated = errors.New("Block is truncated.")
)
const (
@ -91,6 +92,12 @@ type posBuf struct {
}
func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error) {
dataLen := len(data)
if dataLen < 4 {
return nil, ErrBlockTruncated
}
version := data[0]
contentWidth := int(data[2])
@ -132,6 +139,9 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
offset += buf.Pos + 4
buf.Pos = 0
if offset >= dataLen {
return nil, ErrBlockTruncated
}
buf.Data = data[offset:]
if err = zr.(zlib.Resetter).Reset(&buf, nil); err != nil {
@ -151,19 +161,31 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
case version == 23:
offset++
case version == 24:
if offset >= dataLen {
return nil, ErrBlockTruncated
}
ver := data[offset]
offset++
if ver == 1 {
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
num := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2 + 10*num
}
}
offset++
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
numStaticObjects := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2
for i := 0; i < numStaticObjects; i++ {
offset += 13
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
dataSize := int(binary.BigEndian.Uint16(data[offset:]))
offset += dataSize + 2
}
@ -174,23 +196,30 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
var transparent bool
if version >= 22 {
offset++
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
numMappings := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2
// Be a bit more tolerant with truncated node name table.
// We should probably issue an error here, too!?
const outOfBounds = "Offset in node id table out of bounds. Ignored."
for i, n := 0, len(data); i < numMappings; i++ {
if offset+1 >= n {
for i := 0; i < numMappings; i++ {
if offset+1 >= dataLen {
log.Println(outOfBounds)
break
}
nodeId := int32(binary.BigEndian.Uint16(data[offset:]))
offset += 2
if offset+1 >= n {
if offset+1 >= dataLen {
log.Println(outOfBounds)
break
}
nameLen := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2
if offset+nameLen-1 >= n {
if offset+nameLen-1 >= dataLen {
log.Println(outOfBounds)
break
}