tiff: reject TIFF images with unsorted IFD tags.
The spec says that these images are invalid. Add a test with an invalid tiff generated by go-fuzz. Fixes golang/go#10549 Change-Id: I3fd3ae5e607202b41735a2d930f55cb7997f7a9b Reviewed-on: https://go-review.googlesource.com/9377 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
72141d56a2
commit
1be1b0af35
|
@ -118,8 +118,9 @@ func (d *decoder) ifdUint(p []byte) (u []uint, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseIFD decides whether the the IFD entry in p is "interesting" and
|
// parseIFD decides whether the the IFD entry in p is "interesting" and
|
||||||
// stows away the data in the decoder.
|
// stows away the data in the decoder. It returns the tag number of the
|
||||||
func (d *decoder) parseIFD(p []byte) error {
|
// entry and an error, if any.
|
||||||
|
func (d *decoder) parseIFD(p []byte) (int, error) {
|
||||||
tag := d.byteOrder.Uint16(p[0:2])
|
tag := d.byteOrder.Uint16(p[0:2])
|
||||||
switch tag {
|
switch tag {
|
||||||
case tBitsPerSample,
|
case tBitsPerSample,
|
||||||
|
@ -138,17 +139,17 @@ func (d *decoder) parseIFD(p []byte) error {
|
||||||
tImageWidth:
|
tImageWidth:
|
||||||
val, err := d.ifdUint(p)
|
val, err := d.ifdUint(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
d.features[int(tag)] = val
|
d.features[int(tag)] = val
|
||||||
case tColorMap:
|
case tColorMap:
|
||||||
val, err := d.ifdUint(p)
|
val, err := d.ifdUint(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
numcolors := len(val) / 3
|
numcolors := len(val) / 3
|
||||||
if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 {
|
if len(val)%3 != 0 || numcolors <= 0 || numcolors > 256 {
|
||||||
return FormatError("bad ColorMap length")
|
return 0, FormatError("bad ColorMap length")
|
||||||
}
|
}
|
||||||
d.palette = make([]color.Color, numcolors)
|
d.palette = make([]color.Color, numcolors)
|
||||||
for i := 0; i < numcolors; i++ {
|
for i := 0; i < numcolors; i++ {
|
||||||
|
@ -166,15 +167,15 @@ func (d *decoder) parseIFD(p []byte) error {
|
||||||
// must terminate the import process gracefully.
|
// must terminate the import process gracefully.
|
||||||
val, err := d.ifdUint(p)
|
val, err := d.ifdUint(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
for _, v := range val {
|
for _, v := range val {
|
||||||
if v != 1 {
|
if v != 1 {
|
||||||
return UnsupportedError("sample format")
|
return 0, UnsupportedError("sample format")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return int(tag), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// readBits reads n bits from the internal buffer starting at the current offset.
|
// readBits reads n bits from the internal buffer starting at the current offset.
|
||||||
|
@ -428,10 +429,16 @@ func newDecoder(r io.Reader) (*decoder, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevTag := -1
|
||||||
for i := 0; i < len(p); i += ifdLen {
|
for i := 0; i < len(p); i += ifdLen {
|
||||||
if err := d.parseIFD(p[i : i+ifdLen]); err != nil {
|
tag, err := d.parseIFD(p[i : i+ifdLen])
|
||||||
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if tag <= prevTag {
|
||||||
|
return nil, FormatError("tags are not sorted in ascending order")
|
||||||
|
}
|
||||||
|
prevTag = tag
|
||||||
}
|
}
|
||||||
|
|
||||||
d.config.Width = int(d.firstVal(tImageWidth))
|
d.config.Width = int(d.firstVal(tImageWidth))
|
||||||
|
|
|
@ -192,6 +192,24 @@ func TestDecodeLZW(t *testing.T) {
|
||||||
compare(t, img0, img1)
|
compare(t, img0, img1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestDecodeTagOrder tests that a malformed image with unsorted IFD entries is
|
||||||
|
// correctly rejected.
|
||||||
|
func TestDecodeTagOrder(t *testing.T) {
|
||||||
|
data, err := ioutil.ReadFile("../testdata/video-001.tiff")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap the first two IFD entries.
|
||||||
|
ifdOffset := int64(binary.LittleEndian.Uint32(data[4:8]))
|
||||||
|
for i := ifdOffset + 2; i < ifdOffset+14; i++ {
|
||||||
|
data[i], data[i+12] = data[i+12], data[i]
|
||||||
|
}
|
||||||
|
if _, _, err := image.Decode(bytes.NewReader(data)); err == nil {
|
||||||
|
t.Fatal("got nil error, want non-nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestDecompress tests that decoding some TIFF images that use different
|
// TestDecompress tests that decoding some TIFF images that use different
|
||||||
// compression formats result in the same pixel data.
|
// compression formats result in the same pixel data.
|
||||||
func TestDecompress(t *testing.T) {
|
func TestDecompress(t *testing.T) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user