diff --git a/core/Decoder/Png/src/Png.cpp b/core/Decoder/Png/src/Png.cpp index d137df164..cb04f25bd 100644 --- a/core/Decoder/Png/src/Png.cpp +++ b/core/Decoder/Png/src/Png.cpp @@ -138,9 +138,9 @@ std::optional
ParseHeader(std::span 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; diff --git a/core/Decoder/Png/tests/Png.cpp b/core/Decoder/Png/tests/Png.cpp index 7287ed5b3..0c1ac81d1 100644 --- a/core/Decoder/Png/tests/Png.cpp +++ b/core/Decoder/Png/tests/Png.cpp @@ -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(PALETTE_TRNS, size)); + Require(truncated.has_value() && !truncated->hasTransparency); + } + const auto completeTransparency = Decoder::Png::ParseHeader(std::span(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({255, 0, 0, 255, 0, 255, 0, 0, 0, 0, 255, 255, 255, 255, 0, 128})); diff --git a/core/libs/tests/GuestPngDec.cpp b/core/libs/tests/GuestPngDec.cpp index d75515f8c..6bb53f9f6 100644 --- a/core/libs/tests/GuestPngDec.cpp +++ b/core/libs/tests/GuestPngDec.cpp @@ -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};