Merge pull request #2530 from hazzardouslysolid/fix/png-truncated-transparency

fix(png): bound transparency chunk detection to the input
This commit is contained in:
Adrià 2026-10-10 11:20:34 +02:00 committed by GitHub
commit b4a4133c0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 14 additions and 1 deletions

View File

@ -138,9 +138,9 @@ std::optional<Header> ParseHeader(std::span<const std::uint8_t> png) {
while (png.size() - offset >= CHUNK_OVERHEAD) {
const std::uint32_t length = readBigEndian32(&png[offset]);
const std::uint8_t* type = &png[offset + 4];
if (length > png.size() - offset - CHUNK_OVERHEAD) break;
if (isChunkType(type, "tRNS")) header.hasTransparency = true;
if (isChunkType(type, "tRNS") || isChunkType(type, "IDAT") || isChunkType(type, "IEND")) break;
if (length > png.size() - offset - CHUNK_OVERHEAD) break;
offset += CHUNK_OVERHEAD + length;
}
return header;

View File

@ -153,6 +153,12 @@ int main() {
Require(paletteHeader.has_value());
Require(paletteHeader->width == 2 && paletteHeader->height == 2 && paletteHeader->bitDepth == 2);
Require(paletteHeader->colorType == Decoder::Png::ColorType::Palette && paletteHeader->hasTransparency);
for (const std::size_t size : {std::size_t{69}, std::size_t{71}}) {
const auto truncated = Decoder::Png::ParseHeader(std::span<const std::uint8_t>(PALETTE_TRNS, size));
Require(truncated.has_value() && !truncated->hasTransparency);
}
const auto completeTransparency = Decoder::Png::ParseHeader(std::span<const std::uint8_t>(PALETTE_TRNS, 73));
Require(completeTransparency.has_value() && completeTransparency->hasTransparency);
const auto palette = Decoder::Png::Decode(PALETTE_TRNS);
Require(palette.has_value());
Require(palette->pixels == std::vector<std::uint8_t>({255, 0, 0, 255, 0, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 128}));

View File

@ -105,6 +105,13 @@ int main() {
const PngDecParseParam parsePalette{PALETTE_TRNS, sizeof(PALETTE_TRNS), 0};
Require(scePngDecParseHeader(&parsePalette, &info) == 0);
Require(info.color_space == 4 && info.bit_depth == 2 && info.image_flag == 2);
for (const std::uint32_t size : {69u, 71u}) {
const PngDecParseParam truncatedPalette{PALETTE_TRNS, size, 0};
Require(scePngDecParseHeader(&truncatedPalette, &info) == 0);
Require(info.color_space == 4 && info.bit_depth == 2 && info.image_flag == 0);
}
const PngDecParseParam completeTransparency{PALETTE_TRNS, 73, 0};
Require(scePngDecParseHeader(&completeTransparency, &info) == 0 && info.image_flag == 2);
Require(scePngDecParseHeader(nullptr, &info) == invalidParam);
Require(scePngDecParseHeader(&parse, nullptr) == invalidAddr);
const PngDecParseParam parseNull{nullptr, 16, 0};