white-collar daily wear
PARSING PNGS in a different way
PARSING PNGS in a different way

PARSING PNGS in a different way

There are millions of small bugs all around us, in whatever from our desktop applications to the appliances in the kitchen. Hidden, arbitrary conditions that cause unintended outputs as well as behaviors. There are many methods to discover these bugs, however one method we don’t hear about extremely commonly is discovering a bug in your own code, only to recognize somebody else made the exact same mistake. For example, [David Buchanan] discovered a bug in his multi-threaded PNG decoder as well as realized that the Apple PNG decoder had the exact same bug.

PNG (Portable Network Graphics) is an picture style just like JPEG, WEBP, or TIFF designed to replace GIFs. After a header, the rest of the data is completely chunks. Each chunk is prepended by a four-letter identifier, with a few pieces being important chunks. The necessary sections are IHDR (the header), IDAT (actual picture data), PLTE (the combination information), as well as IEND (the last chunk in the file). Compression is via the DEFLATE technique utilized in zlib, which is inherently serial. If you’re interested, there’s a convenient poster about the style from a excellent resource we covered a while back.

Given that DEFLATE is inherently serial, it’s tricky to style the data apropriately. [David] added special sections called pLLD sections (the lowercase very first letter means that it can be safely ignored by decoders that don’t support it). These sections let the decoder understand that a provided IDAT chunk can safely be deserialized concurrently into x pieces. Apple utilizes a similar technique with its iDOT chunks. However, there is an problem here. It is possible for decompress(a+b) != decompress(a) + decompress(b) if a ends halfway with a non-compressed block. since the DEFLATE technique utilizes a window, concating two sections together can create different results.

Since there are now two possible interpretations of a provided PNG, you can craft a PNG to ensure that when decoded serially, it shows one image, as well as when decoded in parallel, it shows another. Additionally, [David] discovered a race condition in desktop safari that results in a somewhat different picture decoded every time. Here’s the PNG being decoded every frame:

[David] composed a bit tool on GitHub to pack two pictures into one PNG. It reminds us of the old technique Steganography, where trick data was stashed inside an image.

(Header picture courtesy of [PawelDecowski]).

Leave a Reply

Your email address will not be published. Required fields are marked *