Module: wine Branch: master Commit: e93495d3f8e1c1e069823c569e3ec58fa5a95ed2 URL: https://source.winehq.org/git/wine.git/?a=commit;h=e93495d3f8e1c1e069823c569...
Author: Akihiro Sagawa sagawa.aki@gmail.com Date: Sun Nov 4 23:17:42 2018 +0900
windowscodecs: Fix buffer overflow when generating a palette.
This typically happens when loading 16-bpp color-keyed grayscale PNG image via GDIPlus.
Signed-off-by: Akihiro Sagawa sagawa.aki@gmail.com Signed-off-by: Vincent Povirk vincent@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/windowscodecs/pngformat.c | 2 +- dlls/windowscodecs/tests/pngformat.c | 68 ++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/dlls/windowscodecs/pngformat.c b/dlls/windowscodecs/pngformat.c index 42a1f2f..3f0ab39 100644 --- a/dlls/windowscodecs/pngformat.c +++ b/dlls/windowscodecs/pngformat.c @@ -1057,7 +1057,7 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface, png_palette[i].blue); } } - else if (color_type == PNG_COLOR_TYPE_GRAY) { + else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth <= 8) { ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values);
if (!ret) diff --git a/dlls/windowscodecs/tests/pngformat.c b/dlls/windowscodecs/tests/pngformat.c index 3648a2e..5f4a5e1 100644 --- a/dlls/windowscodecs/tests/pngformat.c +++ b/dlls/windowscodecs/tests/pngformat.c @@ -539,6 +539,15 @@ static const char png_PLTE_tRNS[] = { 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82 };
+/* grayscale 16 bpp 1x1 pixel PNG image with tRNS chunk */ +static const char png_gray_tRNS[] = { + 0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a, + 0x00,0x00,0x00,0x0d,'I','H','D','R',0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x00,0x00,0x00,0x00,0x6a,0xee,0x47,0x16, + 0x00,0x00,0x00,0x02,'t','R','N','S',0x00,0x00,0x76,0x93,0xcd,0x38, + 0x00,0x00,0x00,0x0b,'I','D','A','T',0x78,0x9c,0x63,0x60,0x60,0x00,0x00,0x00,0x03,0x00,0x01,0xb8,0xad,0x3a,0x63, + 0x00,0x00,0x00,0x00,'I','E','N','D',0xae,0x42,0x60,0x82 +}; + static void test_png_palette(void) { HRESULT hr; @@ -548,6 +557,7 @@ static void test_png_palette(void) GUID format; UINT count, ret; WICColor color[256]; + char *buf;
hr = create_decoder(png_PLTE_tRNS, sizeof(png_PLTE_tRNS), &decoder); ok(hr == S_OK, "Failed to load PNG image data %#x\n", hr); @@ -579,6 +589,64 @@ static void test_png_palette(void) IWICPalette_Release(palette); IWICBitmapFrameDecode_Release(frame); IWICBitmapDecoder_Release(decoder); + + hr = create_decoder(png_gray_tRNS, sizeof(png_gray_tRNS), &decoder); + ok(hr == S_OK, "Failed to load PNG image data %#x\n", hr); + if (hr != S_OK) return; + + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); + ok(hr == S_OK, "GetFrame error %#x\n", hr); + + hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format); + ok(hr == S_OK, "GetPixelFormat error %#x\n", hr); + ok(IsEqualGUID(&format, &GUID_WICPixelFormat64bppRGBA), + "got wrong format %s\n", wine_dbgstr_guid(&format)); + + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(hr == S_OK, "CreatePalette error %#x\n", hr); + hr = IWICBitmapFrameDecode_CopyPalette(frame, palette); + ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "CopyPalette error %#x\n", hr); + + IWICPalette_Release(palette); + IWICBitmapFrameDecode_Release(frame); + IWICBitmapDecoder_Release(decoder); + + /* test 8 bpp grayscale PNG image with tRNS chunk */ + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(png_gray_tRNS)); + memcpy(buf, png_gray_tRNS, sizeof(png_gray_tRNS)); + buf[24] = 8; /* override bit depth */ + + hr = create_decoder(buf, sizeof(png_gray_tRNS), &decoder); + ok(hr == S_OK, "Failed to load PNG image data %#x\n", hr); + if (hr != S_OK) return; + + hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); + ok(hr == S_OK, "GetFrame error %#x\n", hr); + + hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format); + ok(hr == S_OK, "GetPixelFormat error %#x\n", hr); + ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed), + "got wrong format %s\n", wine_dbgstr_guid(&format)); + + hr = IWICImagingFactory_CreatePalette(factory, &palette); + ok(hr == S_OK, "CreatePalette error %#x\n", hr); + hr = IWICBitmapFrameDecode_CopyPalette(frame, palette); + ok(hr == S_OK, "CopyPalette error %#x\n", hr); + + hr = IWICPalette_GetColorCount(palette, &count); + ok(hr == S_OK, "GetColorCount error %#x\n", hr); + ok(count == 256, "expected 256, got %u\n", count); + + hr = IWICPalette_GetColors(palette, 256, color, &ret); + ok(hr == S_OK, "GetColors error %#x\n", hr); + ok(ret == count, "expected %u, got %u\n", count, ret); + ok(color[0] == 0x00000000, "expected 0x00000000, got %#x\n", color[0]); + ok(color[1] == 0xff010101, "expected 0xff010101, got %#x\n", color[1]); + + HeapFree(GetProcessHeap(), 0, buf); + IWICPalette_Release(palette); + IWICBitmapFrameDecode_Release(frame); + IWICBitmapDecoder_Release(decoder); }
/* RGB 24 bpp 1x1 pixel PNG image */