https://bugs.winehq.org/show_bug.cgi?id=40817
Bug ID: 40817 Summary: The last remnat demo does not install Product: Wine Version: 1.9.12 Hardware: x86 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: jeremielapuree@yahoo.fr Distribution: ---
Created attachment 54762 --> https://bugs.winehq.org/attachment.cgi?id=54762 backtrace
The last remnant demo fails to install. Here is the backtrace. Note that I have install the debug symbols, but looks like that is not sufficient to have a useful backtrace.
https://bugs.winehq.org/show_bug.cgi?id=40817
joaopa jeremielapuree@yahoo.fr changed:
What |Removed |Added ---------------------------------------------------------------------------- URL| |http://www.fileplanet.com/1 | |96906/190000/fileinfo/The-L | |ast-Remnant-Trial-Demo-(Nor | |th-American)
https://bugs.winehq.org/show_bug.cgi?id=40817
--- Comment #1 from joaopa jeremielapuree@yahoo.fr --- The games installs if one set the wine version to windows 98. If the version is XP, the installer crashes. I don't know how wine team considers this. Is it considered as a bug or can one close it as INVALID?
https://bugs.winehq.org/show_bug.cgi?id=40817
joaopa jeremielapuree@yahoo.fr changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|The last remnat demo does |The last remnant demo does |not install |not install
https://bugs.winehq.org/show_bug.cgi?id=40817
--- Comment #2 from joaopa jeremielapuree@yahoo.fr --- I must add that the demo readme explicitly requires the XP version to work.
https://bugs.winehq.org/show_bug.cgi?id=40817
--- Comment #3 from joaopa jeremielapuree@yahoo.fr --- Demo works in a real Windows XP box.
https://bugs.winehq.org/show_bug.cgi?id=40817
Louis Lenders xerox.xerox2000x@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |xerox.xerox2000x@gmail.com
--- Comment #4 from Louis Lenders xerox.xerox2000x@gmail.com --- Created attachment 62316 --> https://bugs.winehq.org/attachment.cgi?id=62316 last 2500 of +relay,+seh,+tid log
Confirming and added +relay debuglog
Looks like somthing`s messed up; 0009:Ret KERNEL32.ReadFile() retval=00000001 ret=00404174 0009:Call KERNEL32.lstrlenW(code=c0000005 flags=0 addr=0xf7dabdd3 ip=f7dabdd3 tid=0009 0009:trace:seh:raise_exception info[0]=00000000
However: it starts fine in Staging. I don`t know what patch in Staging fixes this.
@joaopa: can you confirm that the installer starts fine in Staging?
https://bugs.winehq.org/show_bug.cgi?id=40817
Louis Lenders xerox.xerox2000x@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download Status|UNCONFIRMED |NEW Summary|The last remnant demo does |The last remnant demo |not install |installer crashes inside | |kernel32 Ever confirmed|0 |1
--- Comment #5 from Louis Lenders xerox.xerox2000x@gmail.com --- confirming
https://bugs.winehq.org/show_bug.cgi?id=40817
--- Comment #6 from joaopa jeremielapuree@yahoo.fr --- Sorry, I do not use Wine-staging, only vanilla.
https://bugs.winehq.org/show_bug.cgi?id=40817
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|-unknown |ntdll Summary|The last remnant demo |The Last Remnant demo |installer crashes inside |installer crashes on |kernel32 |startup (broken app, | |allocates buffer for | |parsing unicode text files | |one byte too short, NULL | |terminator by chance) Keywords| |Installer CC| |focht@gmx.net
--- Comment #7 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming.
In short: The installer reads multiple unicode .INI files into memory in order parse them on its own. It allocates one byte too short, essentially file_size+1 which is not enough because you need 2 bytes for unicode NULL terminator. When the content has been read into memory, it runs 'lstrlenW()' on the buffer. Depending on the heap usage, 'lstrlenW()' will stop at the first random unicode NULL terminator encountered or if it doesn't find any run out of mapped heap bounds, causing exception.
The installer just works by chance on Windows due to different heap manager implementation which is much more lenient given the gazillion misbehaving/broken apps there. Any decent heap tool ('PageHeap') would also flag this installer/app as "broken".
Wine-Staging just works by chance too. The heap manager modifications (https://github.com/wine-staging/wine-staging/tree/master/patches/ntdll-Heap_...) just make it happen more likely that a random unicode NULL terminator is found until it runs out of mapped heap space (yes, and it gets it wrong sometimes, but no exception).
Installer disassembly, showing broken code:
--- snip --- 004040CC PUSH EBP 004040CD MOV EBP,ESP 004040CF PUSH ECX 004040D0 MOV EAX,DWORD PTR SS:[ARG.1] ... 004040D9 PUSH EDI 004040DA PUSH EBX ; SizeHigh => NULL 004040DB PUSH EAX ; hFile 004040DC CALL DWORD PTR DS:[<&KERNEL32.GetFileSize>] 004040E2 MOV EDI,EAX 004040E4 CMP EDI,-1 004040E7 JE 004041D5 004040ED CMP BYTE PTR SS:[EBP+0C],BL 004040F0 MOV ESI,DWORD PTR DS:[<&KERNEL32.GetProcessHeap>] 004040F6 LEA EAX,[EDI+1] ; file_size += 1 (bug!) 004040FA PUSH 8 ; Flags = HEAP_ZERO_MEMORY 004040FC JNE SHORT 0040414C ... 0040414E PUSH EAX 0040414F CALL DWORD PTR DS:[<&KERNEL32.HeapAlloc>] 00404155 CMP EAX,EBX 00404157 MOV DWORD PTR SS:[EBP+0C],EAX ... 0040415C MOV EAX,DWORD PTR SS:[ARG.1] 0040415F LEA ECX,[LOCAL.1] 00404162 PUSH EBX ; pOverlapped 00404163 PUSH ECX ; pBytesRead 00404164 MOV EAX,DWORD PTR DS:[EAX] 00404166 PUSH EDI ; Size 00404167 PUSH DWORD PTR SS:[ARG.2] ; Buffer => [ARG.2] 0040416A MOV DWORD PTR SS:[LOCAL.1],EBX 0040416D PUSH EAX ; hFile 0040416E CALL DWORD PTR DS:[<&KERNEL32.ReadFile>] 00404174 PUSH DWORD PTR SS:[ARG.2] ; String => [ARG.2] 00404177 TEST EAX,EAX 00404179 JZ SHORT 004041CB 0040417B CALL DWORD PTR DS:[<&KERNEL32.lstrlenW>] 00404181 LEA EAX,[EAX+EAX+2] 00404185 MOV DWORD PTR SS:[ARG.1],EAX 00404188 ADD EAX,3 0040418B AND AL,FC 0040418D CALL 00441DC0 ; Allocates EAX bytes on stack 00404192 MOV EDI,ESP 00404194 PUSH EBX 00404195 PUSH EBX 00404196 PUSH DWORD PTR SS:[EBP+8] 00404199 MOV BYTE PTR DS:[EDI],BL 0040419B PUSH EDI 0040419C PUSH -1 0040419E PUSH DWORD PTR SS:[EBP+0C] 004041A1 PUSH EBX 004041A2 PUSH EBX 004041A3 CALL DWORD PTR DS:[<&KERNEL32.WideCharToMultiByte>] ... --- snip ---
file_size = 0x355C
alloc_buffer(file_size+1) = 0x355D
Heap dump for bad case (with annotations):
--- snip --- 0018FA00 00003560 ; length of block (0x355D rounded to 0x3560 -> align) 0018FA04 03455355 USE ; heap in use MAGIC 0018FA08 000DFEFF ; 0xFEFF byte order mark (BOM), 0xD -> part of CRLF 0018FA0C 005B000A [ ; 0xA LF, "[0x0409]" string start 0018FA10 00780030 0 x 0018FA14 00340030 0 4 0018FA18 00390030 0 9 0018FA1C 000D005D ] 0018FA20 0054000A T 0018FA24 00540049 I T 0018FA28 0045004C L E 0018FA2C 0043003D = C 0018FA30 006F0068 h o 0018FA34 0073006F o s ... 00192F48 00530028 ( S 00192F4C 006D0069 i m 00192F50 006C0070 p l 00192F54 00660069 i f 00192F58 00650069 i e 00192F5C 00290064 d ) 00192F60 000A000D ; 0xD, 0xA -> end of file 00192F64 00525A00 ZR ; garbage -> causes 'lstrlenW()' running further 00192F68 0008D089 00192F6C 45455246 FREE 00192F70 00110088 00192F74 00110298 --- snip ---
Heap dump for random good case (with annotations):
Contents of allocated buffer before 'ReadFile()':
--- snip --- 001533E4 00000000 001533E8 00000000 001533EC 00000000 ; <--- zeroed memory was here before allocation 001533F0 000CCC01 001533F4 45455246 FREE 001533F8 00110088 001533FC 00110298 00153400 00000000 --- snip ---
Contents of allocated buffer after 'ReadFile()':
--- snip --- 001533E4 00290064 d ) 001533E8 000A000D 001533EC 00000000 ; lets 'lstrlenW()' stop by chance 001533F0 000CCC01 001533F4 45455246 FREE 001533F8 00110088 001533FC 00110298 00153400 00000000 --- snip ---
The Wine-Staging case:
--- snip --- ... 00195360 00530028 ( S 00195364 006D0069 i m 00195368 006C0070 p l 0019536C 00660069 i f 00195370 00650069 i e 00195374 00290064 d ) 00195378 000A000D ; end of .INI file content (CR+LF) 0019537C 00525A00 ZR ; garbage 00195380 0008AC6A 00195384 45455246 FREE 00195388 00000000 ; lets 'lstrlenW()' stop by chance --- snip ---
Since the broken app uses 'HEAP_ZERO_MEMORY' one could zero initialize not only the true requested size but the aligned size (tail bytes). This will not work for cases where the requested block was already aligned (no unused tail bytes) and will break heap tail checking/valgrind.
$ sha1sum The_Last_Remnant_NA_Trial_Version.zip 86b093eec133393ef47bb1dcd268b38b12927899 The_Last_Remnant_NA_Trial_Version.zip
$ du -sh The_Last_Remnant_NA_Trial_Version.zip 1.1G The_Last_Remnant_NA_Trial_Version.zip
$ wine --version wine-3.18
Regards
https://bugs.winehq.org/show_bug.cgi?id=40817
zzzzzyzz@hacari.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |zzzzzyzz@hacari.org