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

View File

@ -19,6 +19,7 @@ import (
var ( var (
ErrNoMoreBlocks = errors.New("No more blocks.") ErrNoMoreBlocks = errors.New("No more blocks.")
ErrMapContentSizeMismatch = errors.New("Content size does not match.") ErrMapContentSizeMismatch = errors.New("Content size does not match.")
ErrBlockTruncated = errors.New("Block is truncated.")
) )
const ( const (
@ -91,6 +92,12 @@ type posBuf struct {
} }
func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error) { func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error) {
dataLen := len(data)
if dataLen < 4 {
return nil, ErrBlockTruncated
}
version := data[0] version := data[0]
contentWidth := int(data[2]) contentWidth := int(data[2])
@ -132,6 +139,9 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
offset += buf.Pos + 4 offset += buf.Pos + 4
buf.Pos = 0 buf.Pos = 0
if offset >= dataLen {
return nil, ErrBlockTruncated
}
buf.Data = data[offset:] buf.Data = data[offset:]
if err = zr.(zlib.Resetter).Reset(&buf, nil); err != nil { 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: case version == 23:
offset++ offset++
case version == 24: case version == 24:
if offset >= dataLen {
return nil, ErrBlockTruncated
}
ver := data[offset] ver := data[offset]
offset++ offset++
if ver == 1 { if ver == 1 {
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
num := int(binary.BigEndian.Uint16(data[offset:])) num := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2 + 10*num offset += 2 + 10*num
} }
} }
offset++ offset++
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
numStaticObjects := int(binary.BigEndian.Uint16(data[offset:])) numStaticObjects := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2 offset += 2
for i := 0; i < numStaticObjects; i++ { for i := 0; i < numStaticObjects; i++ {
offset += 13 offset += 13
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
dataSize := int(binary.BigEndian.Uint16(data[offset:])) dataSize := int(binary.BigEndian.Uint16(data[offset:]))
offset += dataSize + 2 offset += dataSize + 2
} }
@ -174,23 +196,30 @@ func NewDecodedBlock(data []byte, colors *Colors) (db *DecodedBlock, err error)
var transparent bool var transparent bool
if version >= 22 { if version >= 22 {
offset++ offset++
if offset+1 >= dataLen {
return nil, ErrBlockTruncated
}
numMappings := int(binary.BigEndian.Uint16(data[offset:])) numMappings := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2 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." 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) log.Println(outOfBounds)
break break
} }
nodeId := int32(binary.BigEndian.Uint16(data[offset:])) nodeId := int32(binary.BigEndian.Uint16(data[offset:]))
offset += 2 offset += 2
if offset+1 >= n { if offset+1 >= dataLen {
log.Println(outOfBounds) log.Println(outOfBounds)
break break
} }
nameLen := int(binary.BigEndian.Uint16(data[offset:])) nameLen := int(binary.BigEndian.Uint16(data[offset:]))
offset += 2 offset += 2
if offset+nameLen-1 >= n { if offset+nameLen-1 >= dataLen {
log.Println(outOfBounds) log.Println(outOfBounds)
break break
} }