- Apply Wine commit 84075591 (user32: Don't access past the file size when loading a cursor/icon) by Alexandre Julliard.
- Add a few consts (also from Wine).
CORE-7027 #comment Ldr and Mm are doing everything right. UPX in fact broke the resource section, and LoadImage is just not handling that correctly. #resolve

svn path=/trunk/; revision=58614
This commit is contained in:
Thomas Faber 2013-03-30 11:17:54 +00:00
parent c0642c44b6
commit b36c9a582f

View file

@ -260,7 +260,7 @@ static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
* The following macro functions account for the irregularities of * The following macro functions account for the irregularities of
* accessing cursor and icon resources in files and resource entries. * accessing cursor and icon resources in files and resource entries.
*/ */
typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n, typedef BOOL (*fnGetCIEntry)( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits ); int *width, int *height, int *bits );
/********************************************************************** /**********************************************************************
@ -268,7 +268,7 @@ typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n,
* *
* Find the icon closest to the requested size and bit depth. * Find the icon closest to the requested size and bit depth.
*/ */
static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry, static int CURSORICON_FindBestIcon( LPCVOID dir, DWORD size, fnGetCIEntry get_entry,
int width, int height, int depth ) int width, int height, int depth )
{ {
int i, cx, cy, bits, bestEntry = -1; int i, cx, cy, bits, bestEntry = -1;
@ -278,7 +278,7 @@ static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry,
/* Find Best Fit */ /* Find Best Fit */
iTotalDiff = 0xFFFFFFFF; iTotalDiff = 0xFFFFFFFF;
iColorDiff = 0xFFFFFFFF; iColorDiff = 0xFFFFFFFF;
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ )
{ {
iTempXDiff = abs(width - cx); iTempXDiff = abs(width - cx);
iTempYDiff = abs(height - cy); iTempYDiff = abs(height - cy);
@ -292,7 +292,7 @@ static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry,
} }
/* Find Best Colors for Best Fit */ /* Find Best Colors for Best Fit */
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ )
{ {
if(abs(width - cx) == iXDiff && abs(height - cy) == iYDiff) if(abs(width - cx) == iXDiff && abs(height - cy) == iYDiff)
{ {
@ -308,14 +308,16 @@ static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry,
return bestEntry; return bestEntry;
} }
static BOOL CURSORICON_GetResIconEntry( LPVOID dir, int n, static BOOL CURSORICON_GetResIconEntry( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits ) int *width, int *height, int *bits )
{ {
CURSORICONDIR *resdir = dir; const CURSORICONDIR *resdir = dir;
ICONRESDIR *icon; const ICONRESDIR *icon;
if ( resdir->idCount <= n ) if ( resdir->idCount <= n )
return FALSE; return FALSE;
if ((const char *)&resdir->idEntries[n + 1] - (const char *)dir > size)
return FALSE;
icon = &resdir->idEntries[n].ResInfo.icon; icon = &resdir->idEntries[n].ResInfo.icon;
*width = icon->bWidth; *width = icon->bWidth;
*height = icon->bHeight; *height = icon->bHeight;
@ -330,7 +332,7 @@ static BOOL CURSORICON_GetResIconEntry( LPVOID dir, int n,
* *
* FIXME: parameter 'color' ignored. * FIXME: parameter 'color' ignored.
*/ */
static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry, static int CURSORICON_FindBestCursor( LPCVOID dir, DWORD size, fnGetCIEntry get_entry,
int width, int height, int depth ) int width, int height, int depth )
{ {
int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1; int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1;
@ -342,7 +344,7 @@ static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry,
/* First find the largest one smaller than or equal to the requested size*/ /* First find the largest one smaller than or equal to the requested size*/
maxwidth = maxheight = 0; maxwidth = maxheight = 0;
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ )
{ {
if ((cx <= width) && (cy <= height) && if ((cx <= width) && (cy <= height) &&
(cx > maxwidth) && (cy > maxheight)) (cx > maxwidth) && (cy > maxheight))
@ -357,7 +359,7 @@ static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry,
/* Now find the smallest one larger than the requested size */ /* Now find the smallest one larger than the requested size */
maxwidth = maxheight = 255; maxwidth = maxheight = 255;
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ ) for ( i = 0; get_entry( dir, size, i, &cx, &cy, &bits ); i++ )
{ {
if (((cx < maxwidth) && (cy < maxheight)) || (bestEntry == -1)) if (((cx < maxwidth) && (cy < maxheight)) || (bestEntry == -1))
{ {
@ -370,14 +372,16 @@ static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry,
return bestEntry; return bestEntry;
} }
static BOOL CURSORICON_GetResCursorEntry( LPVOID dir, int n, static BOOL CURSORICON_GetResCursorEntry( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits ) int *width, int *height, int *bits )
{ {
CURSORICONDIR *resdir = dir; const CURSORICONDIR *resdir = dir;
CURSORDIR *cursor; const CURSORDIR *cursor;
if ( resdir->idCount <= n ) if ( resdir->idCount <= n )
return FALSE; return FALSE;
if ((const char *)&resdir->idEntries[n + 1] - (const char *)dir > size)
return FALSE;
cursor = &resdir->idEntries[n].ResInfo.cursor; cursor = &resdir->idEntries[n].ResInfo.cursor;
*width = cursor->wWidth; *width = cursor->wWidth;
*height = cursor->wHeight; *height = cursor->wHeight;
@ -385,60 +389,62 @@ static BOOL CURSORICON_GetResCursorEntry( LPVOID dir, int n,
return TRUE; return TRUE;
} }
static CURSORICONDIRENTRY *CURSORICON_FindBestIconRes( CURSORICONDIR * dir, static CURSORICONDIRENTRY *CURSORICON_FindBestIconRes( CURSORICONDIR * dir, DWORD size,
int width, int height, int depth ) int width, int height, int depth )
{ {
int n; int n;
n = CURSORICON_FindBestIcon( dir, CURSORICON_GetResIconEntry, n = CURSORICON_FindBestIcon( dir, size, CURSORICON_GetResIconEntry,
width, height, depth ); width, height, depth );
if ( n < 0 ) if ( n < 0 )
return NULL; return NULL;
return &dir->idEntries[n]; return &dir->idEntries[n];
} }
static CURSORICONDIRENTRY *CURSORICON_FindBestCursorRes( CURSORICONDIR *dir, static CURSORICONDIRENTRY *CURSORICON_FindBestCursorRes( CURSORICONDIR *dir, DWORD size,
int width, int height, int depth ) int width, int height, int depth )
{ {
int n = CURSORICON_FindBestCursor( dir, CURSORICON_GetResCursorEntry, int n = CURSORICON_FindBestCursor( dir, size, CURSORICON_GetResCursorEntry,
width, height, depth ); width, height, depth );
if ( n < 0 ) if ( n < 0 )
return NULL; return NULL;
return &dir->idEntries[n]; return &dir->idEntries[n];
} }
static BOOL CURSORICON_GetFileEntry( LPVOID dir, int n, static BOOL CURSORICON_GetFileEntry( LPCVOID dir, DWORD size, int n,
int *width, int *height, int *bits ) int *width, int *height, int *bits )
{ {
CURSORICONFILEDIR *filedir = dir; const CURSORICONFILEDIR *filedir = dir;
CURSORICONFILEDIRENTRY *entry; const CURSORICONFILEDIRENTRY *entry;
BITMAPINFOHEADER *info; const BITMAPINFOHEADER *info;
if ( filedir->idCount <= n ) if ( filedir->idCount <= n )
return FALSE; return FALSE;
if ((const char *)&filedir->idEntries[n + 1] - (const char *)dir > size)
return FALSE;
entry = &filedir->idEntries[n]; entry = &filedir->idEntries[n];
/* FIXME: check against file size */ info = (const BITMAPINFOHEADER *)((const char *)dir + entry->dwDIBOffset);
info = (BITMAPINFOHEADER *)((char *)dir + entry->dwDIBOffset); if ((const char *)(info + 1) - (const char *)dir > size) return FALSE;
*width = entry->bWidth; *width = entry->bWidth;
*height = entry->bHeight; *height = entry->bHeight;
*bits = info->biBitCount; *bits = info->biBitCount;
return TRUE; return TRUE;
} }
static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir, static CURSORICONFILEDIRENTRY *CURSORICON_FindBestCursorFile( CURSORICONFILEDIR *dir, DWORD size,
int width, int height, int depth ) int width, int height, int depth )
{ {
int n = CURSORICON_FindBestCursor( dir, CURSORICON_GetFileEntry, int n = CURSORICON_FindBestCursor( dir, size, CURSORICON_GetFileEntry,
width, height, depth ); width, height, depth );
if ( n < 0 ) if ( n < 0 )
return NULL; return NULL;
return &dir->idEntries[n]; return &dir->idEntries[n];
} }
static CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( CURSORICONFILEDIR *dir, static CURSORICONFILEDIRENTRY *CURSORICON_FindBestIconFile( CURSORICONFILEDIR *dir, DWORD size,
int width, int height, int depth ) int width, int height, int depth )
{ {
int n = CURSORICON_FindBestIcon( dir, CURSORICON_GetFileEntry, int n = CURSORICON_FindBestIcon( dir, size, CURSORICON_GetFileEntry,
width, height, depth ); width, height, depth );
if ( n < 0 ) if ( n < 0 )
return NULL; return NULL;
@ -747,6 +753,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const LPBYTE bits, DWORD bits_size,
icon_data = fram_chunk.data + (2 * sizeof(DWORD)); icon_data = fram_chunk.data + (2 * sizeof(DWORD));
entry = CURSORICON_FindBestIconFile( (CURSORICONFILEDIR *) icon_data, entry = CURSORICON_FindBestIconFile( (CURSORICONFILEDIR *) icon_data,
bits + bits_size - icon_data,
width, height, depth ); width, height, depth );
frame_bits = HeapAlloc( GetProcessHeap(), 0, entry->dwDIBSize ); frame_bits = HeapAlloc( GetProcessHeap(), 0, entry->dwDIBSize );
@ -850,9 +857,9 @@ static HICON CURSORICON_LoadFromFile( LPCWSTR filename,
goto end; goto end;
if ( fCursor ) if ( fCursor )
entry = CURSORICON_FindBestCursorFile( dir, width, height, depth ); entry = CURSORICON_FindBestCursorFile( dir, filesize, width, height, depth );
else else
entry = CURSORICON_FindBestIconFile( dir, width, height, depth ); entry = CURSORICON_FindBestIconFile( dir, filesize, width, height, depth );
if ( !entry ) if ( !entry )
goto end; goto end;
@ -887,6 +894,7 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
HICON hIcon = 0; HICON hIcon = 0;
HRSRC hRsrc; HRSRC hRsrc;
//HRSRC hGroupRsrc; //HRSRC hGroupRsrc;
DWORD size;
CURSORICONDIR *dir; CURSORICONDIR *dir;
CURSORICONDIRENTRY *dirEntry; CURSORICONDIRENTRY *dirEntry;
LPBYTE bits; LPBYTE bits;
@ -915,10 +923,11 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
if (!(handle = LoadResource( hInstance, hRsrc ))) return 0; if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
if (!(dir = LockResource( handle ))) return 0; if (!(dir = LockResource( handle ))) return 0;
size = SizeofResource( hInstance, hRsrc );
if (fCursor) if (fCursor)
dirEntry = CURSORICON_FindBestCursorRes( dir, width, height, depth ); dirEntry = CURSORICON_FindBestCursorRes( dir, size, width, height, depth );
else else
dirEntry = CURSORICON_FindBestIconRes( dir, width, height, depth ); dirEntry = CURSORICON_FindBestIconRes( dir, size, width, height, depth );
if (!dirEntry) return 0; if (!dirEntry) return 0;
wResId = dirEntry->wResId; wResId = dirEntry->wResId;
dwBytesInRes = dirEntry->dwBytesInRes; dwBytesInRes = dirEntry->dwBytesInRes;
@ -1285,9 +1294,9 @@ INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE xdir, BOOL bIcon,
ReleaseDC(0, hdc); ReleaseDC(0, hdc);
if( bIcon ) if( bIcon )
entry = CURSORICON_FindBestIconRes( dir, width, height, depth ); entry = CURSORICON_FindBestIconRes( dir, ~0u, width, height, depth );
else else
entry = CURSORICON_FindBestCursorRes( dir, width, height, depth ); entry = CURSORICON_FindBestCursorRes( dir, ~0u, width, height, depth );
if( entry ) retVal = entry->wResId; if( entry ) retVal = entry->wResId;
} }