Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Beta 1703100617, malloc(): invalid size (unsorted), 'Wonderboy: The Dragons Trap' game fails to launch. #10317

Open
984512547 opened this issue Dec 27, 2023 · 11 comments

Comments

@984512547
Copy link

Your system information

  • Steam client version (build number or date): 1703100617
  • Distribution (e.g. Ubuntu): Devuan Daedalus 5.0
  • Opted into Steam client beta?: Yes
  • Have you checked for system updates?: Yes
  • Steam Logs: [generate by running this command in a terminal tar -zcvf ~/Desktop/steam-logs.tar.gz ~/.steam/steam/logs]
  • GPU: Nvidia

Please describe your issue in as much detail as possible:

  • "Wonderboy: The Dragons Trap" fails to launch using steam beta, possibly due to a malloc issue.
  • The game launches fine using the steams non beta branch.
  • Other games launch fine using the beta.
/bin/sh\0-c\0/home/bob/.steam/debian-installation/ubuntu12_32/reaper SteamLaunch AppId=543260 -- /home/gattsu/.steam/debian-installation/ubuntu12_32/steam-launch-wrapper -- '/home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon'\''s Trap/./WonderBoy'\0
chdir "/home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap"
ERROR: ld.so: object '/home/bob/.steam/debian-installation/ubuntu12_32/gameoverlayrenderer.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
ERROR: ld.so: object 'libgtk3-nocsd.so.0' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS64): ignored.
ERROR: ld.so: object '/home/bob/.steam/debian-installation/ubuntu12_64/gameoverlayrenderer.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS64): ignored.
ERROR: ld.so: object '/home/bob/.steam/debian-installation/ubuntu12_32/gameoverlayrenderer.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
ERROR: ld.so: object '/home/bob/.steam/debian-installation/ubuntu12_32/gameoverlayrenderer.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
ERROR: ld.so: object '/home/bob/.steam/debian-installation/ubuntu12_32/gameoverlayrenderer.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
ERROR: ld.so: object '/home/bob/.steam/debian-installation/ubuntu12_32/gameoverlayrenderer.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
ERROR: ld.so: object '/home/bob/.steam/debian-installation/ubuntu12_32/gameoverlayrenderer.so' from LD_PRELOAD cannot be preloaded (wrong ELF class: ELFCLASS32): ignored.
Setting breakpad minidump AppID = 543260
malloc(): invalid size (unsorted)
/home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/./WonderBoy: line 19: 23660 Aborted ./x86_64/wb.x86_64 $@
Game 543260 created interface SteamUtils009 / Utils
Game 543260 method call count for IClientUtils::RecordSteamInterfaceCreation : 1
Game 543260 method call count for IClientUtils::GetAppID : 2
Uploaded AppInterfaceStats to Steam 

@fibitijibibo

Steps for reproducing this issue:

  1. Use Current Beta '1703100617'
  2. Play "Wonderboy: The Dragons Trap"
@flibitijibibo
Copy link

Woops, I really did typo my own name in that email 😂

Will be back in my office tomorrow morning so I'll try to reproduce locally but it does sound like a recent Steam client change breaks Steamworks in some way. (At least it's not shm this time...)

@flibitijibibo
Copy link

Possibly related: #8542

@flibitijibibo
Copy link

flibitijibibo commented Dec 27, 2023

I wasn't able to reproduce this locally, but I'm testing on SteamOS and Fedora - since it's related to memory I wonder if Valgrind could catch it? Running this should make it work:

LD_LIBRARY_PATH=./x86_64 valgrind ./x86_64/wb.x86_64

It'll probably take forever to start but it should dump a bunch of stacks whenever the program does something wrong, the Steam side may not have the best symbols but it should at least confirm that libsteam_api is where the malloc assert gets hit.

EDIT: Ran valgrind on my end and sure enough Steamworks has some nasty errors:

==9317== Memcheck, a memory error detector
==9317== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==9317== Using Valgrind-3.22.0 and LibVEX; rerun with -h for copyright info
==9317== Command: ./x86_64/wb.x86_64
==9317== 
tid(9317) burning pthread_key_t == 0 so we never use it
Setting breakpad minidump AppID = 543260
==9317== Invalid write of size 2
==9317==    at 0x4E14B91: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E15FC1: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18164: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18F44: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E19D6C: SteamAPI_Init (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4097D1: main (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==9317==  Address 0x83c4e46 is 38 bytes inside a block of size 39 alloc'd
==9317==    at 0x484280F: malloc (vg_replace_malloc.c:442)
==9317==    by 0x532F01E: strdup (strdup.c:42)
==9317==    by 0x52CB806: realpath_stk (canonicalize.c:410)
==9317==    by 0x52CB806: realpath@@GLIBC_2.3 (canonicalize.c:432)
==9317==    by 0x4E14B7B: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E15FC1: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18164: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18F44: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E19D6C: SteamAPI_Init (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4097D1: main (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==9317== 
==9317== Invalid read of size 1
==9317==    at 0x484B654: strlen (vg_replace_strmem.c:502)
==9317==    by 0x4E15FD3: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18164: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18F44: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E19D6C: SteamAPI_Init (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4097D1: main (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==9317==  Address 0x83c4e47 is 0 bytes after a block of size 39 alloc'd
==9317==    at 0x484280F: malloc (vg_replace_malloc.c:442)
==9317==    by 0x532F01E: strdup (strdup.c:42)
==9317==    by 0x52CB806: realpath_stk (canonicalize.c:410)
==9317==    by 0x52CB806: realpath@@GLIBC_2.3 (canonicalize.c:432)
==9317==    by 0x4E14B7B: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E15FC1: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18164: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E18F44: ??? (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4E19D6C: SteamAPI_Init (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==9317==    by 0x4097D1: main (in /home/flibitijibibo/Games/Steam/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==9317==

Wouldn't be surprised if this crashed on the right system.

@kisak-valve
Copy link
Member

kisak-valve commented Dec 27, 2023

Hello @984512547, libgtk3-nocsd is a habitual bad actor. As a basic sanity check, can you remove it from the mix and see if that has any effect?

I'm reminded of #10002 (comment) as a semi-recent example of libgtk3-nocsd misbehaving.

@flibitijibibo
Copy link

If this is on a Wayland desktop, a possible alternative in Wonder Boy's case may be to update the bundled SDL to 2.28.5 and set SDL_VIDEODRIVER=wayland, which should go straight to SSD without GTK in the middle.

@flibitijibibo
Copy link

Pushed a new beta branch on Steam called beta_linux, this rebuilds Wonder Boy against the current flibitBuild system (so it now requires glibc 2.28) and updates to the in-development SDL 2.30. Steamworks I intentionally didn't change since this may very well affect other titles, so it'd be good to fix this for everybody if that's where the problem lies.

@984512547
Copy link
Author

  • Using the command below, the game will launch and not crash, but of course will be running poorly.

LD_LIBRARY_PATH=./x86_64 valgrind ./x86_64/wb.x86_64

==4645== Memcheck, a memory error detector
==4645== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==4645== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==4645== Command: ./x86_64/wb.x86_64
==4645== 
tid(4645) burning pthread_key_t == 0 so we never use it
Setting breakpad minidump AppID = 543260
==4645== Invalid write of size 2
==4645==    at 0x4E14B91: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E15FC1: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18164: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18F44: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E19D6C: SteamAPI_Init (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4097D1: main (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==4645==  Address 0x8385957 is 39 bytes inside a block of size 40 alloc'd
==4645==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==4645==    by 0x52F07F9: strdup (strdup.c:42)
==4645==    by 0x528FB6B: realpath_stk (canonicalize.c:410)
==4645==    by 0x528FB6B: realpath@@GLIBC_2.3 (canonicalize.c:432)
==4645==    by 0x4E14B7B: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E15FC1: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18164: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18F44: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E19D6C: SteamAPI_Init (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4097D1: main (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==4645== 
==4645== Invalid read of size 1
==4645==    at 0x4846794: strlen (vg_replace_strmem.c:494)
==4645==    by 0x4E15FD3: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18164: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18F44: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E19D6C: SteamAPI_Init (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4097D1: main (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==4645==  Address 0x8385958 is 0 bytes after a block of size 40 alloc'd
==4645==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==4645==    by 0x52F07F9: strdup (strdup.c:42)
==4645==    by 0x528FB6B: realpath_stk (canonicalize.c:410)
==4645==    by 0x528FB6B: realpath@@GLIBC_2.3 (canonicalize.c:432)
==4645==    by 0x4E14B7B: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E15FC1: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18164: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E18F44: ??? (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4E19D6C: SteamAPI_Init (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/libsteam_api.so)
==4645==    by 0x4097D1: main (in /home/bob/.steam/debian-installation/steamapps/common/Wonder Boy The Dragon's Trap/x86_64/wb.x86_64)
==4645== 
  • As suggested I removed gtk3-nocsd, rebooted, and the results are still the same using steam beta.

  • Using steam beta along with the games beta_linux branch.

    • Crashes when using the steam client.
    • Using the terminal I got different results.
      • Crashes LD_LIBRARY_PATH=./lib64 ./WonderBoy with or without the provided libSDL2-2.0.so.0
      • Works ./Wonderboy

@flibitijibibo
Copy link

flibitijibibo commented Dec 28, 2023

One possible fix for this would be to take the strdup here in realpath...

https://github.com/bminor/glibc/blob/master/stdlib/canonicalize.c#L409

... and inline it with a change to increase the size of the allocated buffer by 1, to account for the strcat attempt that Steamworks seems to be doing here. strdup.c just uses strlen + 1 for the buffer size, so changing it to be strlen + 2 with a Note of Shame explaining the inlined routine could be a change that the Steam Runtime does (and only SLR, no way is this getting upstreamed) to accommodate Steamworks versions from 2012-2017 which have this bug.

It's either that or detect the affected .so files in every depot and swap them out with hotfixed versions behind everybody's back somehow, not sure which is worse!

@flibitijibibo
Copy link

flibitijibibo commented Dec 28, 2023

Sorry for all the double posting, but! Out of curiosity I took a look at musl and they just always allocate PATH_MAX, which seemed like overkill until I looked at the Linux man page for realpath:

If resolved_path is specified as NULL, then realpath() uses malloc(3) to allocate a buffer of up to PATH_MAX bytes to hold the resolved pathname, and returns a pointer to this buffer.

The Open Group spec is unfortunately more vague:

If resolved_name is a null pointer, the generated pathname shall be stored as a null-terminated string in a buffer allocated as if by a call to malloc().

I'm inclined to say the former is enough to make the call that standard strdup is not as good a fit for realpath as a specialized version that always does PATH_MAX to ensure that the buffer is always the right size no matter how the path is used afterward (in other words, if paths were their own data type, we would want to duplicate a path and not a generic string).

This is at least slightly easier to justify having a patch for, though I still wouldn't want to be the one that tries to submit a change that increases memory use in most cases...

@flibitijibibo
Copy link

Threw this together, pretty sure this has to be filed on glibc's Bugzilla first, but this at least does what I suggested yesterday:

From 8fde1bf88ff0185eb5b074550a144c7003cbe8c8 Mon Sep 17 00:00:00 2001
From: Ethan Lee <flibitijibibo@gmail.com>
Date: Thu, 28 Dec 2023 18:59:15 -0500
Subject: [PATCH] stdlib: realpath should always allocate a buffer of PATH_MAX
 size.

Consider the following example:

  extern char *somepath;
  char *path = realpath(somepath, NULL);
  strcat(path, "/");

It is common to append directory separators to paths, but when realpath
allocates the buffer the size cannot be determined from the outside. While the
application can provide its own buffer, it is reasonable for an application to
assume that a path buffer will be able to fit a full path string even if it gets
modified after the call is made.

realpath_stk now always allocates a buffer of PATH_MAX size, so that the path
can be modified by the caller as safely as possible.

Fixes a crash in the Steamworks SDK, which prior to 2017 always assumed that the
buffer returned by realpath had room to append a directory separator to the end.

Signed-off-by: Ethan Lee <flibitijibibo@gmail.com>
---
 stdlib/canonicalize.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
index 7e421ef115..219bda7079 100644
--- a/stdlib/canonicalize.c
+++ b/stdlib/canonicalize.c
@@ -406,7 +406,23 @@ error:
       if (failed)
 	return NULL;
       else
-	return __strdup (bufs->rname.data);
+        {
+          idx_t path_max = get_path_max ();
+
+          if (dest - rname > path_max)
+            {
+              __set_errno (ENAMETOOLONG);
+              return NULL;
+            }
+
+          char *alloc_path = (char *) malloc (path_max);
+
+          if (alloc_path == NULL)
+            return NULL;
+
+          strcpy (alloc_path, bufs->rname.data);
+          return alloc_path;
+        }
     }
 }
 
-- 
2.43.0

@flibitijibibo
Copy link

Guess that's a "no" until someone overrules it: https://sourceware.org/bugzilla/show_bug.cgi?id=31198

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants