From ca6ba492690135647443817ba0d3ccb0c2f0de14 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Sun, 12 Jul 2015 21:02:13 +1000 Subject: [PATCH] image/png: don't read filter bytes for empty interlace passes. Fixes #11604 The gray-gradient.png image was created by a Go program: ---- package main import ( "image" "image/color" "image/png" "log" "os" ) func main() { f, err := os.Create("a.png") if err != nil { log.Fatal(err) } defer f.Close() m := image.NewGray(image.Rect(0, 0, 1, 16)) for i := 0; i < 16; i++ { m.SetGray(0, i, color.Gray{uint8(i * 0x11)}) } err = png.Encode(f, m) if err != nil { log.Fatal(err) } } ---- The equivalent gray-gradient.interlaced.png image was created via ImageMagick: $ convert -interlace PNG gray-gradient.png gray-gradient.interlaced.png As a sanity check: $ file gray-gradient.* gray-gradient.interlaced.png: PNG image data, 1 x 16, 4-bit grayscale, interlaced gray-gradient.png: PNG image data, 1 x 16, 8-bit grayscale, non-interlaced Change-Id: I7700284f74d1ea30073aede3bce4d7651787bdbc Reviewed-on: https://go-review.googlesource.com/12064 Reviewed-by: Rob Pike Reviewed-by: Brad Fitzpatrick --- src/image/png/reader.go | 13 ++++++++++++- src/image/png/reader_test.go | 15 +++++++++++++++ .../png/testdata/gray-gradient.interlaced.png | Bin 0 -> 247 bytes src/image/png/testdata/gray-gradient.png | Bin 0 -> 77 bytes 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 src/image/png/testdata/gray-gradient.interlaced.png create mode 100644 src/image/png/testdata/gray-gradient.png diff --git a/src/image/png/reader.go b/src/image/png/reader.go index 33218e1516..bbd6f753fa 100644 --- a/src/image/png/reader.go +++ b/src/image/png/reader.go @@ -340,7 +340,9 @@ func (d *decoder) decode() (image.Image, error) { if err != nil { return nil, err } - d.mergePassInto(img, imagePass, pass) + if imagePass != nil { + d.mergePassInto(img, imagePass, pass) + } } } @@ -382,6 +384,12 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image // Add the multiplication factor and subtract one, effectively rounding up. width = (width - p.xOffset + p.xFactor - 1) / p.xFactor height = (height - p.yOffset + p.yFactor - 1) / p.yFactor + // A PNG image can't have zero width or height, but for an interlaced + // image, an individual pass might have zero width or height. If so, we + // shouldn't even read a per-row filter type byte, so return early. + if width == 0 || height == 0 { + return nil, nil + } } switch d.cb { case cbG1, cbG2, cbG4, cbG8: @@ -457,6 +465,9 @@ func (d *decoder) readImagePass(r io.Reader, pass int, allocateOnly bool) (image cdat[i] += p } case ftAverage: + // The first column has no column to the left of it, so it is a + // special case. We know that the first column exists because we + // check above that width != 0, and so len(cdat) != 0. for i := 0; i < bytesPerPixel; i++ { cdat[i] += pdat[i] / 2 } diff --git a/src/image/png/reader_test.go b/src/image/png/reader_test.go index 1f92f8c221..f89e7efe7f 100644 --- a/src/image/png/reader_test.go +++ b/src/image/png/reader_test.go @@ -13,6 +13,7 @@ import ( "io" "io/ioutil" "os" + "reflect" "strings" "testing" ) @@ -320,6 +321,20 @@ func TestPalettedDecodeConfig(t *testing.T) { } } +func TestInterlaced(t *testing.T) { + a, err := readPNG("testdata/gray-gradient.png") + if err != nil { + t.Fatal(err) + } + b, err := readPNG("testdata/gray-gradient.interlaced.png") + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(a, b) { + t.Fatalf("decodings differ:\nnon-interlaced:\n%#v\ninterlaced:\n%#v", a, b) + } +} + func TestIncompleteIDATOnRowBoundary(t *testing.T) { // The following is an invalid 1x2 grayscale PNG image. The header is OK, // but the zlib-compressed IDAT payload contains two bytes "\x02\x00", diff --git a/src/image/png/testdata/gray-gradient.interlaced.png b/src/image/png/testdata/gray-gradient.interlaced.png new file mode 100644 index 0000000000000000000000000000000000000000..01f657ae86da8ad45a9ebc89a4642c8b13d42f68 GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{F0%ABYPyYj?S<)SS9T^zg78t&m77yezC3(BM zFz{O$*)0b0I14-?i-EKU7`vU!wgWOWJzX3_IIbrrBxEEMBv>3+aA3lL4Gj+&n;DuJ zof(`N53{uK@`y_Sl_o2&H@fU9E(B^)Epd$~Nl7e8wMs5Z1yT$~28O1(2IjhkMj=K9 yRwm|FCT7}(237_JLXpKzC>nC}Q!>*kF*O*PLNrM6+-C=BVDNPHb6Mw<&;$TzjXTW% literal 0 HcmV?d00001 diff --git a/src/image/png/testdata/gray-gradient.png b/src/image/png/testdata/gray-gradient.png new file mode 100644 index 0000000000000000000000000000000000000000..6de1cd36f4acb4509c38cba4a8efd099c8adec7e GIT binary patch literal 77 zcmeAS@N?(olHy`uVBq!ia0vp^j6f{F0VEhceeuc$QX-x%jv*Cul9CdHj_^wUV`gGt Z`2Sx>nu+I$s8kY2ou{jx%Q~loCIC&I5uX46 literal 0 HcmV?d00001 -- 2.50.0