kernelbase: Fix GetFileVersionInfo*() crashes with malformed resources.
Some Unity games ship with an encrypted Assembly-CSharp.dll, including the resources directory, yet the engine still calls GetFileVersionInfoSizeW() on those files. This may results in a page fault when trying to find the version resource and takes the whole process down. The change fixes crashes when launching Home Behind 2 and Crown Trick. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50075 Signed-off-by: Arkadiusz Hiler <ahiler@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
31fab6705a
commit
e51ae86937
|
@ -240,7 +240,8 @@ done:
|
||||||
* Copied from loader/pe_resource.c
|
* Copied from loader/pe_resource.c
|
||||||
*/
|
*/
|
||||||
static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY *dir,
|
static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY *dir,
|
||||||
WORD id, const void *root )
|
WORD id, const void *root,
|
||||||
|
DWORD root_size )
|
||||||
{
|
{
|
||||||
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
|
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
|
||||||
int min, max, pos;
|
int min, max, pos;
|
||||||
|
@ -248,11 +249,19 @@ static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DI
|
||||||
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
|
entry = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(dir + 1);
|
||||||
min = dir->NumberOfNamedEntries;
|
min = dir->NumberOfNamedEntries;
|
||||||
max = min + dir->NumberOfIdEntries - 1;
|
max = min + dir->NumberOfIdEntries - 1;
|
||||||
|
|
||||||
|
if (max >= (root_size - ((INT_PTR)dir - (INT_PTR)root) - sizeof(*dir)) / sizeof(*entry))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
while (min <= max)
|
while (min <= max)
|
||||||
{
|
{
|
||||||
pos = (min + max) / 2;
|
pos = (min + max) / 2;
|
||||||
if (entry[pos].u.Id == id)
|
if (entry[pos].u.Id == id)
|
||||||
return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].u2.s2.OffsetToDirectory);
|
{
|
||||||
|
DWORD offset = entry[pos].u2.s2.OffsetToDirectory;
|
||||||
|
if (offset > root_size - sizeof(*dir)) return NULL;
|
||||||
|
return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + offset);
|
||||||
|
}
|
||||||
if (entry[pos].u.Id > id) max = pos - 1;
|
if (entry[pos].u.Id > id) max = pos - 1;
|
||||||
else min = pos + 1;
|
else min = pos + 1;
|
||||||
}
|
}
|
||||||
|
@ -294,7 +303,8 @@ static inline int push_language( WORD *list, int pos, WORD lang )
|
||||||
* find_entry_language
|
* find_entry_language
|
||||||
*/
|
*/
|
||||||
static const IMAGE_RESOURCE_DIRECTORY *find_entry_language( const IMAGE_RESOURCE_DIRECTORY *dir,
|
static const IMAGE_RESOURCE_DIRECTORY *find_entry_language( const IMAGE_RESOURCE_DIRECTORY *dir,
|
||||||
const void *root, DWORD flags )
|
const void *root, DWORD root_size,
|
||||||
|
DWORD flags )
|
||||||
{
|
{
|
||||||
const IMAGE_RESOURCE_DIRECTORY *ret;
|
const IMAGE_RESOURCE_DIRECTORY *ret;
|
||||||
WORD list[9];
|
WORD list[9];
|
||||||
|
@ -319,7 +329,7 @@ static const IMAGE_RESOURCE_DIRECTORY *find_entry_language( const IMAGE_RESOURCE
|
||||||
pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
|
pos = push_language( list, pos, MAKELANGID( LANG_ENGLISH, SUBLANG_DEFAULT ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < pos; i++) if ((ret = find_entry_by_id( dir, list[i], root ))) return ret;
|
for (i = 0; i < pos; i++) if ((ret = find_entry_by_id( dir, list[i], root, root_size ))) return ret;
|
||||||
return find_entry_default( dir, root );
|
return find_entry_default( dir, root );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +423,7 @@ static BOOL find_pe_resource( HANDLE handle, DWORD *resLen, DWORD *resOff, DWORD
|
||||||
PIMAGE_DATA_DIRECTORY resDataDir;
|
PIMAGE_DATA_DIRECTORY resDataDir;
|
||||||
PIMAGE_SECTION_HEADER sections;
|
PIMAGE_SECTION_HEADER sections;
|
||||||
LPBYTE resSection;
|
LPBYTE resSection;
|
||||||
DWORD len, section_size, data_size;
|
DWORD len, section_size, data_size, resDirSize;
|
||||||
const void *resDir;
|
const void *resDir;
|
||||||
const IMAGE_RESOURCE_DIRECTORY *resPtr;
|
const IMAGE_RESOURCE_DIRECTORY *resPtr;
|
||||||
const IMAGE_RESOURCE_DATA_ENTRY *resData;
|
const IMAGE_RESOURCE_DATA_ENTRY *resData;
|
||||||
|
@ -486,21 +496,22 @@ static BOOL find_pe_resource( HANDLE handle, DWORD *resLen, DWORD *resOff, DWORD
|
||||||
|
|
||||||
/* Find resource */
|
/* Find resource */
|
||||||
resDir = resSection + (resDataDir->VirtualAddress - sections[i].VirtualAddress);
|
resDir = resSection + (resDataDir->VirtualAddress - sections[i].VirtualAddress);
|
||||||
|
resDirSize = section_size - (resDataDir->VirtualAddress - sections[i].VirtualAddress);
|
||||||
|
|
||||||
resPtr = resDir;
|
resPtr = resDir;
|
||||||
resPtr = find_entry_by_id( resPtr, VS_FILE_INFO, resDir );
|
resPtr = find_entry_by_id( resPtr, VS_FILE_INFO, resDir, resDirSize );
|
||||||
if ( !resPtr )
|
if ( !resPtr )
|
||||||
{
|
{
|
||||||
TRACE("No typeid entry found\n" );
|
TRACE("No typeid entry found\n" );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
resPtr = find_entry_by_id( resPtr, VS_VERSION_INFO, resDir );
|
resPtr = find_entry_by_id( resPtr, VS_VERSION_INFO, resDir, resDirSize );
|
||||||
if ( !resPtr )
|
if ( !resPtr )
|
||||||
{
|
{
|
||||||
TRACE("No resid entry found\n" );
|
TRACE("No resid entry found\n" );
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
resPtr = find_entry_language( resPtr, resDir, flags );
|
resPtr = find_entry_language( resPtr, resDir, resDirSize, flags );
|
||||||
if ( !resPtr )
|
if ( !resPtr )
|
||||||
{
|
{
|
||||||
TRACE("No default language entry found\n" );
|
TRACE("No default language entry found\n" );
|
||||||
|
|
Loading…
Reference in New Issue