Commit e08a5fb0 authored by Fredrik Söderquist's avatar Fredrik Söderquist Committed by Commit Bot

Fail PNG size parsing if we encounter an unknown critical chunk

"Apple optimized" PNG-formatted images contain a "CgBI" chunk as the
first in the file. PNGImageReader::ParseSize() did not fail on critical
chunks that it didn't recognize, so we managed to thus parse out the
dimensions of the image and ended dispatching 'load' for it (rather than
'error').

Bug: 994740
Change-Id: I6b9ddb4290cf43e3ca2f491aa1b500dedeb0316b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1760918Reviewed-by: default avatarLeon Scroggins <scroggo@chromium.org>
Commit-Queue: Fredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#688637}
parent dcd997c1
...@@ -1460,4 +1460,14 @@ TEST(AnimatedPNGTests, TrnsMeansAlpha) { ...@@ -1460,4 +1460,14 @@ TEST(AnimatedPNGTests, TrnsMeansAlpha) {
ASSERT_TRUE(frame->HasAlpha()); ASSERT_TRUE(frame->HasAlpha());
} }
TEST(PNGTests, CriticalPrivateChunkBeforeIHDR) {
auto decoder = CreatePNGDecoder();
scoped_refptr<SharedBuffer> data =
ReadFile(kDecodersTestingDir, "private-critical-chunk-before-ihdr.png");
EXPECT_FALSE(data->IsEmpty());
decoder->SetData(data.get(), true);
EXPECT_FALSE(decoder->IsSizeAvailable());
EXPECT_TRUE(decoder->Failed());
}
} // namespace blink } // namespace blink
...@@ -630,19 +630,20 @@ bool PNGImageReader::ParseSize(const FastSharedBufferReader& reader) { ...@@ -630,19 +630,20 @@ bool PNGImageReader::ParseSize(const FastSharedBufferReader& reader) {
} else if (IsChunk(chunk, "fdAT")) { } else if (IsChunk(chunk, "fdAT")) {
ignore_animation_ = true; ignore_animation_ = true;
} else { } else {
bool ihdr = IsChunk(chunk, "IHDR"); auto is_necessary_ancillary = [](const png_byte* chunk) {
auto is_necessary = [](const png_byte* chunk) { for (const char* tag : {"tRNS", "cHRM", "iCCP", "sRGB", "gAMA"}) {
for (const char* tag :
{"PLTE", "IEND", "tRNS", "cHRM", "iCCP", "sRGB", "gAMA"}) {
if (IsChunk(chunk, tag)) if (IsChunk(chunk, tag))
return true; return true;
} }
return false; return false;
}; };
if (ihdr || is_necessary(chunk)) { // Determine if the chunk type of |chunk| is "critical".
// (Ancillary bit == 0; the chunk is required for display).
bool is_critical_chunk = (chunk[4] & 1u << 5) == 0;
if (is_critical_chunk || is_necessary_ancillary(chunk)) {
png_process_data(png_, info_, const_cast<png_byte*>(chunk), 8); png_process_data(png_, info_, const_cast<png_byte*>(chunk), 8);
ProcessData(reader, read_offset_ + 8, length + 4); ProcessData(reader, read_offset_ + 8, length + 4);
if (ihdr) { if (IsChunk(chunk, "IHDR")) {
parsed_ihdr_ = true; parsed_ihdr_ = true;
ihdr_offset_ = read_offset_; ihdr_offset_ = read_offset_;
width_ = png_get_image_width(png_, info_); width_ = png_get_image_width(png_, info_);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment