https://bugs.winehq.org/show_bug.cgi?id=57758
--- Comment #8 from Paul Gofman pgofman@codeweavers.com --- Created attachment 78047 --> https://bugs.winehq.org/attachment.cgi?id=78047 PoC patch (not a fix really)
So I managed to get the game and reproduced the problem.
Reverting blamed commit indeed fixes the crash, although the only effect of the patch is that it changes which bytes are modified on the stack, and those bytes are later used uninitialized by the game.
I am attaching the patch which clearly illustrates that and "fixes" the issue (but please don't treat that as an attempt to fix it, that is absolutely insane and I am attaching it purely for illustration purposes).
The actual crash in the generated code. The game generates some code specific to probably screen size or some other parameters on the fly and then it crashes jumping to NULL address. The generation of code blocks is performed based on some string translation encoding that, like "4 D=S", which generates instructions (which patterns later possibly combined). Such string is passed to function at address 0x150314B0 in storm.dll on stack (previously strcpy'ed from the game data). That function ends up parsing it beyond the end terminator, not entirely sure due to it expects it double NULL terminated or it is a bug in the function itself, but it parses it beyond zero terminator reading leftover unitialized stack data. The fatal error or success depends on what is there. It is tolerant to the wide range of garbage on stack, but if there happens to be 'S' before zero it generates the broken code pattern. I confirmed with debugger on Windows that:
- There is also garbage, so it is not like we are using more stack than Windows, just the bytes are different and on Windows (like in Wine previously) the problematic condition of 'S' before 0 is not met. - Setting these leftover stack data on Windows in debugger to satisfy the problematic condition yields the same crash.
So in my case in that stack garbage, when the game is installed at default location C:/Program Files/Starcraft , there is a part of this path here. Renaming Starcraft so it doesn't contain 'S' (e. g., to "Qtarcraft") works around the issue here. But that should not be necessarily the case with Wine build differently, e. g., with a different version of gcc; while such renaming also has good chances to help. Using a shorter path (placing the game in C:/q instead) doesn't help: then in the leftover stack data contains some string mapping data with characters 01-FF and then it still hits 'S' before 0.
So that so far looks not sanely fixable to me. It works by chance on Windows, worked by chance on Wine and maybe will work again eventually once something else in the functions on the way of GetModuleHandle() randomly changes.
If that was, e. g., about not touching that stack from Wine (using less of the stack in some functions) there maybe could be a valid fix, but this is not the case: we are not using much of stack on that path and there is also garbage on Windows, just without 'S'.
Maybe a workaround that has some chance of working is renaming game's Starcraft directory to anything with the same size without 'S'.