image/tiff: do not allow zero bits per sample
Fuzzing detected a divide by zero in images with 0 bits per sample. Instead of panicing, return an error. Do more validation of bits per sample so that the package only supports what we've actually tested. Fixes golang/go#10711. Change-Id: Ib41b5cd798c32b06429164c9bc471f5f321d88c5 Reviewed-on: https://go-review.googlesource.com/10943 Reviewed-by: Benny Siegert <bsiegert@gmail.com> Reviewed-by: Nigel Tao <nigeltao@golang.org>
This commit is contained in:
parent
d8e202c6ce
commit
3157439762
|
@ -231,7 +231,7 @@ func (d *decoder) decode(dst image.Image, xmin, ymin, xmax, ymax int) error {
|
||||||
off += 2
|
off += 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if d.bpp == 8 {
|
} else {
|
||||||
var off int
|
var off int
|
||||||
n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
|
n := 1 * len(d.features[tBitsPerSample]) // bytes per sample times samples per pixel
|
||||||
for y := ymin; y < ymax; y++ {
|
for y := ymin; y < ymax; y++ {
|
||||||
|
@ -436,6 +436,14 @@ func newDecoder(r io.Reader) (*decoder, error) {
|
||||||
return nil, FormatError("BitsPerSample tag missing")
|
return nil, FormatError("BitsPerSample tag missing")
|
||||||
}
|
}
|
||||||
d.bpp = d.firstVal(tBitsPerSample)
|
d.bpp = d.firstVal(tBitsPerSample)
|
||||||
|
switch d.bpp {
|
||||||
|
case 0:
|
||||||
|
return nil, FormatError("BitsPerSample must not be 0")
|
||||||
|
case 1, 8, 16:
|
||||||
|
// Nothing to do, these are accepted by this implementation.
|
||||||
|
default:
|
||||||
|
return nil, UnsupportedError(fmt.Sprintf("BitsPerSample of %v", d.bpp))
|
||||||
|
}
|
||||||
|
|
||||||
// Determine the image mode.
|
// Determine the image mode.
|
||||||
switch d.firstVal(tPhotometricInterpretation) {
|
switch d.firstVal(tPhotometricInterpretation) {
|
||||||
|
|
|
@ -255,12 +255,35 @@ func TestLargeIFDEntry(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestZeroBitsPerSample verifies that an IFD with a bitsPerSample of 0 does not cause a crash.
|
||||||
|
// Issue 10711.
|
||||||
|
func TestZeroBitsPerSample(t *testing.T) {
|
||||||
|
contents, err := ioutil.ReadFile(testdataDir + "bw-deflate.tiff")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutate the loaded image to have the problem.
|
||||||
|
// 02 01: tag number (tBitsPerSample)
|
||||||
|
// 03 00: data type (short, or uint16)
|
||||||
|
// 01 00 00 00: count
|
||||||
|
// ?? 00 00 00: value (1 -> 0)
|
||||||
|
find := []byte{2, 1, 3, 0, 1, 0, 0, 0, 1, 0, 0, 0}
|
||||||
|
repl := []byte{2, 1, 3, 0, 1, 0, 0, 0, 0, 0, 0, 0}
|
||||||
|
contents = bytes.Replace(contents, find, repl, 1)
|
||||||
|
|
||||||
|
_, err = Decode(bytes.NewReader(contents))
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("Decode with 0 bits per sample: got nil error, want non-nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// benchmarkDecode benchmarks the decoding of an image.
|
// benchmarkDecode benchmarks the decoding of an image.
|
||||||
func benchmarkDecode(b *testing.B, filename string) {
|
func benchmarkDecode(b *testing.B, filename string) {
|
||||||
b.StopTimer()
|
b.StopTimer()
|
||||||
contents, err := ioutil.ReadFile(testdataDir + filename)
|
contents, err := ioutil.ReadFile(testdataDir + filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
r := &buffer{buf: contents}
|
r := &buffer{buf: contents}
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user