]> Cypherpunks repositories - gostls13.git/commitdiff
image/png: don't read filter bytes for empty interlace passes.
authorNigel Tao <nigeltao@golang.org>
Sun, 12 Jul 2015 11:02:13 +0000 (21:02 +1000)
committerNigel Tao <nigeltao@golang.org>
Mon, 13 Jul 2015 06:40:00 +0000 (06:40 +0000)
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 <r@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/image/png/reader.go
src/image/png/reader_test.go
src/image/png/testdata/gray-gradient.interlaced.png [new file with mode: 0644]
src/image/png/testdata/gray-gradient.png [new file with mode: 0644]

index 33218e15160ae0a09d1ebf84a1907f2dd8ea962c..bbd6f753fadc4fcdcd9e54e250fbd887580ea152 100644 (file)
@@ -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
                        }
index 1f92f8c221b96018691abe23ece7772fd71c9cc6..f89e7efe7fedebb97d31970e34def3d2089ac755 100644 (file)
@@ -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 (file)
index 0000000..01f657a
Binary files /dev/null and b/src/image/png/testdata/gray-gradient.interlaced.png differ
diff --git a/src/image/png/testdata/gray-gradient.png b/src/image/png/testdata/gray-gradient.png
new file mode 100644 (file)
index 0000000..6de1cd3
Binary files /dev/null and b/src/image/png/testdata/gray-gradient.png differ