gdi32: Add parameter validation in GetDIBits.

This commit is contained in:
Alexandre Julliard 2011-08-29 11:30:36 +02:00
parent 43240527b6
commit 4e3c649b9c
2 changed files with 125 additions and 11 deletions

View File

@ -180,7 +180,7 @@ static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *
src_colors = (char *)info + info->bmiHeader.biSize;
colors = get_dib_num_of_colors( dst );
if (info->bmiHeader.biCompression == BI_BITFIELDS)
if (dst->bmiHeader.biCompression == BI_BITFIELDS)
{
/* bitfields are always at bmiColors even in larger structures */
memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
@ -929,6 +929,9 @@ INT WINAPI GetDIBits(
/* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
own copy and transfer the colour info back at the end */
if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
if (bits &&
(dst_info->bmiHeader.biCompression == BI_JPEG || dst_info->bmiHeader.biCompression == BI_PNG))
return 0;
dst_info->bmiHeader.biClrUsed = 0;
dst_info->bmiHeader.biClrImportant = 0;
@ -946,12 +949,6 @@ INT WINAPI GetDIBits(
funcs = get_bitmap_funcs( bmp );
if (dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
{
ret = fill_query_info( info, bmp );
goto done;
}
src.visrect.left = 0;
src.visrect.top = 0;
src.visrect.right = bmp->bitmap.bmWidth;
@ -965,6 +962,45 @@ INT WINAPI GetDIBits(
if (lines == 0 || startscan >= dst.visrect.bottom)
bits = NULL;
if (!bits && dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
{
ret = fill_query_info( info, bmp );
goto done;
}
/* validate parameters */
if (dst_info->bmiHeader.biWidth <= 0) goto done;
if (dst_info->bmiHeader.biHeight == 0) goto done;
switch (dst_info->bmiHeader.biCompression)
{
case BI_RLE4:
if (dst_info->bmiHeader.biBitCount != 4) goto done;
if (dst_info->bmiHeader.biHeight < 0) goto done;
if (bits) goto done; /* can't retrieve compressed bits */
break;
case BI_RLE8:
if (dst_info->bmiHeader.biBitCount != 8) goto done;
if (dst_info->bmiHeader.biHeight < 0) goto done;
if (bits) goto done; /* can't retrieve compressed bits */
break;
case BI_BITFIELDS:
if (dst_info->bmiHeader.biBitCount != 16 && dst_info->bmiHeader.biBitCount != 32) goto done;
/* fall through */
case BI_RGB:
if (lines && !dst_info->bmiHeader.biPlanes) goto done;
if (dst_info->bmiHeader.biBitCount == 1) break;
if (dst_info->bmiHeader.biBitCount == 4) break;
if (dst_info->bmiHeader.biBitCount == 8) break;
if (dst_info->bmiHeader.biBitCount == 16) break;
if (dst_info->bmiHeader.biBitCount == 24) break;
if (dst_info->bmiHeader.biBitCount == 32) break;
/* fall through */
default:
goto done;
}
if (bits)
{
if (dst_info->bmiHeader.biHeight > 0)

View File

@ -884,9 +884,27 @@ static void test_dib_formats(void)
case 32: expect_ok = (compr == BI_RGB || compr == BI_BITFIELDS); break;
default: expect_ok = FALSE; break;
}
if (!planes) expect_ok = FALSE;
todo = (compr == BI_BITFIELDS); /* wine doesn't like strange bitfields */
memset( bi, 0, sizeof(bi->bmiHeader) );
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biWidth = 2;
bi->bmiHeader.biHeight = 2;
bi->bmiHeader.biPlanes = planes;
bi->bmiHeader.biBitCount = bpp;
bi->bmiHeader.biCompression = compr;
bi->bmiHeader.biSizeImage = 0;
memset( bi->bmiColors, 0xaa, sizeof(RGBQUAD) * 256 );
ret = GetDIBits(hdc, hbmp, 0, 0, data, bi, DIB_RGB_COLORS);
if (expect_ok || (!bpp && compr != BI_JPEG && compr != BI_PNG) ||
(bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8))
ok( ret, "GetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( !ret || broken(!bpp && (compr == BI_JPEG || compr == BI_PNG)), /* nt4 */
"GetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
/* all functions check planes except GetDIBits with 0 lines */
if (!planes) expect_ok = FALSE;
memset( bi, 0, sizeof(bi->bmiHeader) );
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biWidth = 2;
@ -947,9 +965,27 @@ static void test_dib_formats(void)
broken((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)), /* nt4 */
"StretchDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
ret = GetDIBits(hdc, hbmp, 0, 2, data, bi, DIB_RGB_COLORS);
if (expect_ok)
ok( ret, "GetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( !ret, "GetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
ok( bi->bmiHeader.biBitCount == bpp, "GetDIBits modified bpp %u/%u\n",
bpp, bi->bmiHeader.biBitCount );
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biWidth = 2;
bi->bmiHeader.biHeight = 2;
bi->bmiHeader.biPlanes = planes;
bi->bmiHeader.biBitCount = bpp;
bi->bmiHeader.biCompression = compr;
bi->bmiHeader.biSizeImage = 1;
memset( bi->bmiColors, 0xaa, sizeof(RGBQUAD) * 256 );
/* RLE allowed with valid biSizeImage */
if ((bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8)) expect_ok = TRUE;
ret = SetDIBits(hdc, hbmp, 0, 1, data, bi, DIB_RGB_COLORS);
if (expect_ok || (bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8))
if (expect_ok)
{
if (todo)
todo_wine ok( ret, "SetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
@ -959,12 +995,12 @@ static void test_dib_formats(void)
else
ok( !ret, "SetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
ret = SetDIBitsToDevice( memdc, 0, 0, 1, 1, 0, 0, 0, 1, data, bi, DIB_RGB_COLORS );
if (expect_ok || (bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8))
if (expect_ok)
ok( ret, "SetDIBitsToDevice failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( !ret, "SetDIBitsToDevice succeeded for %u/%u/%u\n", bpp, planes, compr );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
if (expect_ok || (bpp == 4 && compr == BI_RLE4) || (bpp == 8 && compr == BI_RLE8))
if (expect_ok)
{
if (todo)
todo_wine ok( ret, "StretchDIBits failed for %u/%u/%u\n", bpp, planes, compr );
@ -973,6 +1009,13 @@ static void test_dib_formats(void)
}
else
ok( !ret, "StretchDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
bi->bmiHeader.biSizeImage = 0;
ret = GetDIBits(hdc, hbmp, 0, 2, NULL, bi, DIB_RGB_COLORS);
if (expect_ok || !bpp)
ok( ret, "GetDIBits failed for %u/%u/%u\n", bpp, planes, compr );
else
ok( !ret, "GetDIBits succeeded for %u/%u/%u\n", bpp, planes, compr );
}
}
}
@ -1001,6 +1044,17 @@ static void test_dib_formats(void)
ok( ret, "SetDIBitsToDevice failed with null bitfields\n" );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
todo_wine ok( ret, "StretchDIBits failed with null bitfields\n" );
ret = GetDIBits(hdc, hbmp, 0, 2, data, bi, DIB_RGB_COLORS);
ok( ret, "GetDIBits failed with null bitfields\n" );
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = 16;
bi->bmiHeader.biCompression = BI_BITFIELDS;
bi->bmiHeader.biSizeImage = 0;
*(DWORD *)&bi->bmiColors[0] = 0;
*(DWORD *)&bi->bmiColors[1] = 0;
*(DWORD *)&bi->bmiColors[2] = 0;
ret = GetDIBits(hdc, hbmp, 0, 2, NULL, bi, DIB_RGB_COLORS);
ok( ret, "GetDIBits failed with null bitfields\n" );
/* all fields must be non-zero */
*(DWORD *)&bi->bmiColors[0] = 3;
@ -1035,6 +1089,14 @@ static void test_dib_formats(void)
ok( !ret, "SetDIBitsToDevice succeeded with negative width\n" );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
ok( !ret, "StretchDIBits succeeded with negative width\n" );
ret = GetDIBits(hdc, hbmp, 0, 2, data, bi, DIB_RGB_COLORS);
ok( !ret, "GetDIBits succeeded with negative width\n" );
bi->bmiHeader.biWidth = -2;
bi->bmiHeader.biHeight = 2;
bi->bmiHeader.biBitCount = 32;
bi->bmiHeader.biCompression = BI_RGB;
ret = GetDIBits(hdc, hbmp, 0, 2, NULL, bi, DIB_RGB_COLORS);
ok( !ret || broken(ret), /* nt4 */ "GetDIBits succeeded with negative width\n" );
bi->bmiHeader.biWidth = 0;
bi->bmiHeader.biHeight = 2;
@ -1051,6 +1113,14 @@ static void test_dib_formats(void)
ok( !ret || broken(ret), /* nt4 */ "SetDIBitsToDevice succeeded with zero width\n" );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
ok( !ret || broken(ret), /* nt4 */ "StretchDIBits succeeded with zero width\n" );
ret = GetDIBits(hdc, hbmp, 0, 2, data, bi, DIB_RGB_COLORS);
ok( !ret, "GetDIBits succeeded with zero width\n" );
bi->bmiHeader.biWidth = 0;
bi->bmiHeader.biHeight = 2;
bi->bmiHeader.biBitCount = 32;
bi->bmiHeader.biCompression = BI_RGB;
ret = GetDIBits(hdc, hbmp, 0, 2, NULL, bi, DIB_RGB_COLORS);
ok( !ret || broken(ret), /* nt4 */ "GetDIBits succeeded with zero width\n" );
bi->bmiHeader.biWidth = 2;
bi->bmiHeader.biHeight = 0;
@ -1067,6 +1137,14 @@ static void test_dib_formats(void)
ok( !ret, "SetDIBitsToDevice succeeded with zero height\n" );
ret = StretchDIBits( memdc, 0, 0, 1, 1, 0, 0, 1, 1, data, bi, DIB_RGB_COLORS, SRCCOPY );
ok( !ret, "StretchDIBits succeeded with zero height\n" );
ret = GetDIBits(hdc, hbmp, 0, 2, data, bi, DIB_RGB_COLORS);
ok( !ret || broken(ret), /* nt4 */ "GetDIBits succeeded with zero height\n" );
bi->bmiHeader.biWidth = 2;
bi->bmiHeader.biHeight = 0;
bi->bmiHeader.biBitCount = 32;
bi->bmiHeader.biCompression = BI_RGB;
ret = GetDIBits(hdc, hbmp, 0, 2, NULL, bi, DIB_RGB_COLORS);
ok( !ret || broken(ret), /* nt4 */ "GetDIBits succeeded with zero height\n" );
DeleteDC( memdc );
DeleteObject( hbmp );