The game calls GetFileVersionInfoSizeW(L"CrownTrick_Data\\Managed\\Assembly-CSharp.dll") which causes the crash.
Turns out that Assembly-CSharp.dll has malformed resource table - the size defined in the PE header is 0x400 but the table claims to have 20k+ entries in it.
Wine allocs the space for the resource table and then reads the data into it. When it tries to look for the VS_FILE_INFO it just trust the provided number of entries which result in a read outside that allocated area == a page fault.
diff --git a/dlls/kernelbase/version.c b/dlls/kernelbase/version.c
index 58c49aa148b..d8619c61538 100644
--- a/dlls/kernelbase/version.c
+++ b/dlls/kernelbase/version.c
@@ -240,7 +240,8 @@ done:
* Copied from loader/pe_resource.c
*/
static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DIRECTORY *dir,
- WORD id, const void *root )
+ WORD id, const void *root,
+ const void *end )
{
const IMAGE_RESOURCE_DIRECTORY_ENTRY *entry;
int min, max, pos;
@@ -251,6 +252,7 @@ static const IMAGE_RESOURCE_DIRECTORY *find_entry_by_id( const IMAGE_RESOURCE_DI
while (min <= max)
{
pos = (min + max) / 2;
+ if ((void*)&entry[pos] >= end) return NULL;
if (entry[pos].u.Id == id)
return (const IMAGE_RESOURCE_DIRECTORY *)((const char *)root + entry[pos].u2.s2.OffsetToDirectory);
if (entry[pos].u.Id > id) max = pos - 1;
@@ -294,7 +296,8 @@ static inline int push_language( WORD *list, int pos, WORD lang )
* find_entry_language
*/
static const IMAGE_RESOURCE_DIRECTORY *find_entry_language( const IMAGE_RESOURCE_DIRECTORY *dir,
- const void *root, DWORD flags )
+ const void *root, const void *end,
+ DWORD flags )
{
const IMAGE_RESOURCE_DIRECTORY *ret;
WORD list[9];
@@ -319,7 +322,7 @@ static const IMAGE_RESOURCE_DIRECTORY *find_entry_language( const IMAGE_RESOURCE
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, end ))) return ret;
return find_entry_default( dir, root );
}
@@ -488,19 +491,19 @@ static BOOL find_pe_resource( HANDLE handle, DWORD *resLen, DWORD *resOff, DWORD
resDir = resSection + (resDataDir->VirtualAddress - sections[i].VirtualAddress);
resPtr = resDir;
- resPtr = find_entry_by_id( resPtr, VS_FILE_INFO, resDir );
+ resPtr = find_entry_by_id( resPtr, VS_FILE_INFO, resDir, resSection + section_size );
if ( !resPtr )
{
TRACE("No typeid entry found\n" );
goto done;
}
- resPtr = find_entry_by_id( resPtr, VS_VERSION_INFO, resDir );
+ resPtr = find_entry_by_id( resPtr, VS_VERSION_INFO, resDir, resSection + section_size );
if ( !resPtr )
{
TRACE("No resid entry found\n" );
goto done;
}
- resPtr = find_entry_language( resPtr, resDir, flags );
+ resPtr = find_entry_language( resPtr, resDir, resSection + section_size, flags );
if ( !resPtr )
{
TRACE("No default language entry found\n" );
I'll look into getting a proper solution into upstream Wine / Proton.
Hello @chtaube, it looks like https://www.winehq.org/pipermail/wine-devel/2021-March/181915.html has been tentatively added to Proton Experimental and it may be worthwhile to retest this game with the experimental build.
@chtaube This fix is now in Proton 6.3-1. Please report back if you are still seeing the crash :)
Proton 7 and Experimental
Game takes all the RAM it can get in matter of seconds. Freezes whole desktop if left unattended for a little bit longer.
It happens before any window is generated or displayed.
Proton 7 and Experimental
Game takes all the RAM it can get in matter of seconds. Freezes whole desktop if left unattended for a little bit longer. It happens before any window is generated or displayed.
Proton 9 and still doing the same
Compatibility Report
System Information
I confirm:
Symptoms
Most times, Steam cannot start the game. But sometimes it works and then the game runs without notable issues. The attached log files are from two successive start attempts, where the first start failed and the second start succeeded.