Commit 267109d6 authored by Alexandre Julliard's avatar Alexandre Julliard

user32: Add size checks when creating an icon from bitmap info.

parent 03395f2d
...@@ -796,11 +796,11 @@ done: ...@@ -796,11 +796,11 @@ done:
* *
* Create an icon from its BITMAPINFO. * Create an icon from its BITMAPINFO.
*/ */
static HICON create_icon_from_bmi( BITMAPINFO *bmi, HMODULE module, LPCWSTR resname, HRSRC rsrc, static HICON create_icon_from_bmi( const BITMAPINFO *bmi, DWORD maxsize, HMODULE module, LPCWSTR resname,
POINT hotspot, BOOL bIcon, INT width, INT height, UINT cFlag ) HRSRC rsrc, POINT hotspot, BOOL bIcon, INT width, INT height,
UINT cFlag )
{ {
unsigned int size = bitmap_info_size( bmi, DIB_RGB_COLORS ); DWORD size, color_size, mask_size;
BOOL monochrome = is_dib_monochrome( bmi );
HBITMAP color = 0, mask = 0, alpha = 0; HBITMAP color = 0, mask = 0, alpha = 0;
const void *color_bits, *mask_bits; const void *color_bits, *mask_bits;
BITMAPINFO *bmi_copy; BITMAPINFO *bmi_copy;
...@@ -811,14 +811,35 @@ static HICON create_icon_from_bmi( BITMAPINFO *bmi, HMODULE module, LPCWSTR resn ...@@ -811,14 +811,35 @@ static HICON create_icon_from_bmi( BITMAPINFO *bmi, HMODULE module, LPCWSTR resn
/* Check bitmap header */ /* Check bitmap header */
if (maxsize < sizeof(BITMAPCOREHEADER))
{
WARN( "invalid size %u\n", maxsize );
return 0;
}
if (maxsize < bmi->bmiHeader.biSize)
{
WARN( "invalid header size %u\n", bmi->bmiHeader.biSize );
return 0;
}
if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) && if ( (bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
(bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) || (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER) ||
(bmi->bmiHeader.biCompression != BI_RGB && (bmi->bmiHeader.biCompression != BI_RGB &&
bmi->bmiHeader.biCompression != BI_BITFIELDS)) ) bmi->bmiHeader.biCompression != BI_BITFIELDS)) )
{ {
WARN_(cursor)("\tinvalid resource bitmap header.\n"); WARN( "invalid bitmap header %u\n", bmi->bmiHeader.biSize );
return 0;
}
size = bitmap_info_size( bmi, DIB_RGB_COLORS );
color_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2,
bmi->bmiHeader.biBitCount );
mask_size = get_dib_image_size( bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight / 2, 1 );
if (size > maxsize || color_size > maxsize - size)
{
WARN( "truncated file %u < %u+%u+%u\n", maxsize, size, color_size, mask_size );
return 0; return 0;
} }
if (mask_size > maxsize - size - color_size) mask_size = 0; /* no mask */
if (cFlag & LR_DEFAULTSIZE) if (cFlag & LR_DEFAULTSIZE)
{ {
...@@ -856,11 +877,10 @@ static HICON create_icon_from_bmi( BITMAPINFO *bmi, HMODULE module, LPCWSTR resn ...@@ -856,11 +877,10 @@ static HICON create_icon_from_bmi( BITMAPINFO *bmi, HMODULE module, LPCWSTR resn
bmi_copy->bmiHeader.biHeight /= 2; bmi_copy->bmiHeader.biHeight /= 2;
color_bits = (const char*)bmi + size; color_bits = (const char*)bmi + size;
mask_bits = (const char*)color_bits + mask_bits = (const char*)color_bits + color_size;
get_dib_image_size( bmi->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, bmi->bmiHeader.biBitCount );
alpha = 0; alpha = 0;
if (monochrome) if (is_dib_monochrome( bmi ))
{ {
if (!(mask = CreateBitmap( width, height * 2, 1, 1, NULL ))) goto done; if (!(mask = CreateBitmap( width, height * 2, 1, 1, NULL ))) goto done;
color = 0; color = 0;
...@@ -908,10 +928,13 @@ static HICON create_icon_from_bmi( BITMAPINFO *bmi, HMODULE module, LPCWSTR resn ...@@ -908,10 +928,13 @@ static HICON create_icon_from_bmi( BITMAPINFO *bmi, HMODULE module, LPCWSTR resn
} }
} }
if (mask_size)
{
SelectObject( hdc, mask ); SelectObject( hdc, mask );
StretchDIBits( hdc, 0, 0, width, height, StretchDIBits( hdc, 0, 0, width, height,
0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight, 0, 0, bmi_copy->bmiHeader.biWidth, bmi_copy->bmiHeader.biHeight,
mask_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY ); mask_bits, bmi_copy, DIB_RGB_COLORS, SRCCOPY );
}
ret = TRUE; ret = TRUE;
done: done:
...@@ -1170,7 +1193,6 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size, ...@@ -1170,7 +1193,6 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size,
bits + bits_size - icon_data, bits + bits_size - icon_data,
width, height, depth, loadflags ); width, height, depth, loadflags );
bmi = (const BITMAPINFO *) (icon_data + entry->dwDIBOffset);
info->hotspot.x = entry->xHotspot; info->hotspot.x = entry->xHotspot;
info->hotspot.y = entry->yHotspot; info->hotspot.y = entry->yHotspot;
if (!header.width || !header.height) if (!header.width || !header.height)
...@@ -1184,9 +1206,16 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size, ...@@ -1184,9 +1206,16 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size,
frameHeight = header.height; frameHeight = header.height;
} }
frames[i] = NULL;
if (entry->dwDIBOffset < bits + bits_size - icon_data)
{
bmi = (const BITMAPINFO *) (icon_data + entry->dwDIBOffset);
/* Grab a frame from the animation */ /* Grab a frame from the animation */
frames[i] = create_icon_from_bmi( (BITMAPINFO *)bmi, NULL, NULL, NULL, info->hotspot, frames[i] = create_icon_from_bmi( bmi, bits + bits_size - (const BYTE *)bmi,
NULL, NULL, NULL, info->hotspot,
is_icon, frameWidth, frameHeight, loadflags ); is_icon, frameWidth, frameHeight, loadflags );
}
if (!frames[i]) if (!frames[i])
{ {
FIXME_(cursor)("failed to convert animated cursor frame.\n"); FIXME_(cursor)("failed to convert animated cursor frame.\n");
...@@ -1250,8 +1279,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size, ...@@ -1250,8 +1279,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size,
/********************************************************************** /**********************************************************************
* CreateIconFromResourceEx (USER32.@) * CreateIconFromResourceEx (USER32.@)
* *
* FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something * FIXME: Convert to mono when cFlag is LR_MONOCHROME.
* with cbSize parameter as well.
*/ */
HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize, HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
BOOL bIcon, DWORD dwVersion, BOOL bIcon, DWORD dwVersion,
...@@ -1290,9 +1318,10 @@ HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize, ...@@ -1290,9 +1318,10 @@ HICON WINAPI CreateIconFromResourceEx( LPBYTE bits, UINT cbSize,
hotspot.x = pt[0]; hotspot.x = pt[0];
hotspot.y = pt[1]; hotspot.y = pt[1];
bmi = (BITMAPINFO *)(pt + 2); bmi = (BITMAPINFO *)(pt + 2);
cbSize -= 2 * sizeof(*pt);
} }
return create_icon_from_bmi( bmi, NULL, NULL, NULL, hotspot, bIcon, width, height, cFlag ); return create_icon_from_bmi( bmi, cbSize, NULL, NULL, NULL, hotspot, bIcon, width, height, cFlag );
} }
...@@ -1350,8 +1379,8 @@ static HICON CURSORICON_LoadFromFile( LPCWSTR filename, ...@@ -1350,8 +1379,8 @@ static HICON CURSORICON_LoadFromFile( LPCWSTR filename,
hotspot.x = entry->xHotspot; hotspot.x = entry->xHotspot;
hotspot.y = entry->yHotspot; hotspot.y = entry->yHotspot;
hIcon = create_icon_from_bmi( (BITMAPINFO *)&bits[entry->dwDIBOffset], NULL, NULL, NULL, hIcon = create_icon_from_bmi( (BITMAPINFO *)&bits[entry->dwDIBOffset], filesize - entry->dwDIBOffset,
hotspot, !fCursor, width, height, loadflags ); NULL, NULL, NULL, hotspot, !fCursor, width, height, loadflags );
end: end:
TRACE("loaded %s -> %p\n", debugstr_w( filename ), hIcon ); TRACE("loaded %s -> %p\n", debugstr_w( filename ), hIcon );
UnmapViewOfFile( bits ); UnmapViewOfFile( bits );
...@@ -1438,6 +1467,7 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, ...@@ -1438,6 +1467,7 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
} }
if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
size = SizeofResource( hInstance, hRsrc );
bits = LockResource( handle ); bits = LockResource( handle );
if (!fCursor) if (!fCursor)
...@@ -1451,8 +1481,9 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name, ...@@ -1451,8 +1481,9 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
hotspot.x = pt[0]; hotspot.x = pt[0];
hotspot.y = pt[1]; hotspot.y = pt[1];
bits += 2 * sizeof(SHORT); bits += 2 * sizeof(SHORT);
size -= 2 * sizeof(SHORT);
} }
hIcon = create_icon_from_bmi( (BITMAPINFO *)bits, hInstance, name, hRsrc, hIcon = create_icon_from_bmi( (BITMAPINFO *)bits, size, hInstance, name, hRsrc,
hotspot, !fCursor, width, height, loadflags ); hotspot, !fCursor, width, height, loadflags );
FreeResource( handle ); FreeResource( handle );
return hIcon; return hIcon;
......
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