protonscr

Crown Trick

protonopen appid 1000010Game compatibility - Unofficial
ValveSoftware/Proton#4308 · opened 2020-10-23 by chtaube · updated 2024-06-11 · 5 comments · github · game page · search this game
Cchtaube 2020-10-23 github

Compatibility Report

  • Name of the game with compatibility issues: Crown Trick
  • Steam AppID of the game: 1000010

System Information

  • OS: Debian GNU/Linux bullseye/sid
  • GPU: Radeon RX 5500 XT (NAVI14, DRM 3.38.0, 5.8.0-3-amd64, LLVM 10.0.1)
  • Driver/LLVM version: Mesa 20.1.9
  • Kernel version: Linux 5.8.0-3-amd64 #1 SMP Debian 5.8.14-1 (2020-10-10) x86_64 GNU/Linux
  • Link to full system information report as Gist: Steam System Information
  • Proton version: 5.13-1

I confirm:

  • [X] that I haven't found an existing compatibility report for this game.
  • [X] that I have checked whether there are updates for my system available.

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.

Iivyl 2020-10-28 github

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.

Something like this fixes the problem for me... (expand)

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.

Kkisak-valve maintainer 2021-03-03 github

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.

Aalasky17 2021-04-01 github

@chtaube This fix is now in Proton 6.3-1. Please report back if you are still seeing the crash :)

Mmalfunctioning-object 2022-04-07 github

PC information

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.

DDekosAnjo 2024-06-11 github

PC information

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
image

Proton versions

DLLs