Skip to content

Commit

Permalink
[bplist] Add some checks from CoreFoundation; add more tests.
Browse files Browse the repository at this point in the history
Fixes some crashes found via fuzzing; refs #15.
  • Loading branch information
DHowett committed Mar 20, 2017
1 parent 8af31b0 commit 429a406
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
34 changes: 30 additions & 4 deletions bplist.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,10 +375,31 @@ func (p *bplistParser) parseDocument() (pval cfValue, parseError error) {
panic(err)
}

if p.trailer.NumObjects > uint64(math.Pow(2, 8*float64(p.trailer.ObjectRefSize))) {
if p.trailer.OffsetTableOffset >= uint64(p.trailerOffset) {
panic(fmt.Errorf("binary property list offset table beyond beginning of trailer (0x%x, trailer@0x%x)", p.trailer.OffsetTableOffset, p.trailerOffset))
}

if p.trailer.OffsetTableOffset < 9 {
panic(fmt.Errorf("binary property list offset table begins inside header (0x%x)", p.trailer.OffsetTableOffset))
}

if uint64(p.trailerOffset) > (p.trailer.NumObjects*uint64(p.trailer.OffsetIntSize))+p.trailer.OffsetTableOffset {
panic(errors.New("binary property list contains garbage between offset table and trailer"))
}

if p.trailer.NumObjects > uint64(p.trailerOffset) {
panic(fmt.Errorf("binary property list contains more objects (%v) than there are non-trailer bytes in the file (%v)", p.trailer.NumObjects, p.trailerOffset))
}

objectRefSize := uint64(1) << (8 * p.trailer.ObjectRefSize)
if p.trailer.NumObjects > objectRefSize {
panic(fmt.Errorf("binary property list contains more objects (%v) than its object ref size (%v bytes) can support", p.trailer.NumObjects, p.trailer.ObjectRefSize))
}

if p.trailer.OffsetIntSize < uint8(8) && (uint64(1)<<(8*p.trailer.OffsetIntSize)) <= p.trailer.OffsetTableOffset {
panic(errors.New("binary property offset size isn't big enough to address entire file"))
}

if p.trailer.TopObject >= p.trailer.NumObjects {
panic(fmt.Errorf("top object index %v is out of range (only %v objects exist)", p.trailer.TopObject, p.trailer.NumObjects))
}
Expand All @@ -390,10 +411,11 @@ func (p *bplistParser) parseDocument() (pval cfValue, parseError error) {
panic(err)
}

maxOffset := p.trailer.OffsetTableOffset - 1
for i := uint64(0); i < p.trailer.NumObjects; i++ {
off, _ := p.readSizedInt(int(p.trailer.OffsetIntSize))
if off >= uint64(p.trailerOffset) {
panic(fmt.Errorf("object %v starts beyond end of plist trailer (%v vs %v)", i, off, p.trailerOffset))
if off > maxOffset {
panic(fmt.Errorf("object %v starts beyond beginning of object table (0x%x, table@0x%x)", i, off, maxOffset+1))
}
p.offtable[i] = off
}
Expand All @@ -405,7 +427,11 @@ func (p *bplistParser) parseDocument() (pval cfValue, parseError error) {
}

for pvalp, off := range p.delayedObjects {
*pvalp = p.valueAtOffset(off)
if pval, ok := p.objrefs[off]; ok {
*pvalp = pval
} else {
panic(fmt.Errorf("object@0x%x not referenced by object table", off))
}
}

pval = p.valueAtOffset(p.offtable[p.trailer.TopObject])
Expand Down
35 changes: 35 additions & 0 deletions invalid_bplist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,41 @@ var InvalidBplists []string = []string{
"bplist00\xd6\x0100000\a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\xa2\x1b\x1c00000000000000000000000000000000\b\x8300\x01\x01\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa6",
"bplist00\xd6\x0100000\a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\b000\x01\x01\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa6",
"bplist00\xd5\x01\x02\x03\x04\x05\x06\a\b\t\n000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\x1300000000\b\xa6\x01\x01\x00\x00\x00\x00\x00\x00\x00\v\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xaf",
"bplist00\a\x000000000\x0000" +
"0000\x0000000000",
"bplist00\x06\a\n\v\f\x0f\x1aYbool" +
"a5@SV[taTdateloatsXi" +
"ntacrayWstrings\xa2\b\t\t\b" +
"D\x01\x02\x03\x04A\xb8Euldluox\x00\x00\x00\xa2\r" +
"\x0e5551512312578271\xa1\xaf\"" +
"7\xe1021#(/8@CDJS181583" +
"404541015625@SV[\x83\xd0\x01\x01" +
"\x00\x00\x00\x00\x00\x00\x00\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
"\x00\x00\x00\x10",
"bplist00\xd2\x01\x02\x03\x040000000" +
"0000000000000000\x10\n\b\x01" +
"\x01\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
"\x00\x00\x00\x00$",
"bplist00\xa8\x01\x02\x03\x04\x05\x06\a\b000" +
"\x0f\xff\x11\xff\xff\x12\x00\x0f\xffš\x00\xff\xff\xff\x12\x0f\xff\xff\xff" +
"\x12\xff\xff\xff\xff\x13\xff\xff\xff\xff\xff\xff\xff\xff\b\x1e\x01\x01\x00\x00" +
"\x00\x00\x00\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
"\x006",
"bplist01253906250\x02\x05\x00" +
"\x00\x00\x00\x80\x00\x00\t\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" +
"\x00\x006",
"bplist00000000000000" +
"000\x0000000000",
"bplist00000000000000" +
"00000000000000000000" +
"00000000000000000000" +
"00000000000000000000" +
"00000000000000000000" +
"0000000000000\xdf\x0400000" +
"00000000000000000000" +
"00000000000000000000" +
"000000q000\x01\x01\x00\x00\x00\x00\x00\x00\x00\x1d" +
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa6",
}

func TestInvalidBinaryPlists(t *testing.T) {
Expand Down

0 comments on commit 429a406

Please sign in to comment.