Skip to content

image/png: Integer underflow bug on 32-bit systems #12687

@yalue

Description

@yalue

I noticed this bug in Go 1.5.1 (and earlier versions) on windows/386, but it doesn't affect 64-bit versions (at least not versions that use a 64-bit int type).

The reason for this can be found on line 733 of image/png/reader.go, where min(len(ignored), int(length)) is calculated. length is a 32-bit unsigned value and already guaranteed to be greater than 0. On 64-bit systems, a value of length greater than 0x80000000 will be converted to a valid int because an int value is larger than 32 bits. After the conversion, the value will be safely ignored in favor of len(ignored), which is 4096. On 32-bit systems, however, this value will pass the initial positivity check, but will then become negative when converted to a 32-bit int. This negative value will be seen as the smaller of the two values by min, leading it to be used as an array bound and therefore the panic.

The code shown below attempts to decode a clearly invalid PNG image, but panics instead of returning an error on 32-bit systems:

package main

import (
    "bytes"
    "fmt"
    "image/png"
)

func main() {
    data := []byte{0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0xff, 0xff,
        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
        0xd3, 0x11, 0x9a, 0x73, 0x00, 0x00, 0xf8, 0x1e, 0xf3, 0x2e, 0x00, 0x00,
        0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf4, 0x7c, 0x55, 0x04, 0x1a,
        0xd3}
    _, e := png.Decode(bytes.NewReader(data))
    if e != nil {
        fmt.Printf("Got error: %s\n", e)
    } else {
        fmt.Printf("That should have been an error!\n")
    }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions