[Bug 30720] The Last Remnant Demo (non-steam) installer crashes on startup (application bug, heap management)

wine-bugs at winehq.org wine-bugs at winehq.org
Tue Dec 17 12:03:27 CST 2013


http://bugs.winehq.org/show_bug.cgi?id=30720

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |Installer
                URL|http://news.bigdownload.com |http://www.fileplanet.com/1
                   |/2009/02/26/download-the-la |96906/190000/fileinfo/The-L
                   |st-remnant-demo/            |ast-Remnant-Trial-%28North-
                   |                            |American%29
                 CC|                            |focht at gmx.net
          Component|gdi32                       |ntdll
            Summary|The Last Remnant            |The Last Remnant Demo
                   |demo(non-steam): installer  |(non-steam) installer
                   |crashes immediately         |crashes on startup
                   |                            |(application bug, heap
                   |                            |management)

--- Comment #7 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

it's as Alexandre said - the installer contains a stupid bug which just works
by chance with Windows (differences in heap management/implementation).

Let me elaborate a bit ... ;-)

Relevant part of trace log:

--- snip ---
$ WINEDEBUG=+tid,+seh,+relay,+msi wine ./setup.exe >>log.txt 2>&1
...
0024:Call KERNEL32.CreateFileA(0048b569 "Z:\\home\\focht\\Downloads\\The Last
Remnant Trial
Version\\0x0409.ini",80000000,00000001,00000000,00000003,00000001,00000000)
ret=0040d95b
0024:Ret  KERNEL32.CreateFileA() retval=00000074 ret=0040d95b
0024:Call KERNEL32.ReadFile(00000074,0033d0a0,00000400,0033d4a0,00000000)
ret=00404d5c
0024:Ret  KERNEL32.ReadFile() retval=00000001 ret=00404d5c
0024:Call KERNEL32.SetFilePointer(00000074,00000000,00000000,00000000)
ret=00404da9
0024:Ret  KERNEL32.SetFilePointer() retval=00000000 ret=00404da9
0024:Call KERNEL32.GetFileSize(00000074,00000000) ret=004040e2
0024:Ret  KERNEL32.GetFileSize() retval=0000355c ret=004040e2
0024:Call ntdll.RtlAllocateHeap(00110000,00000008,0000355d) ret=00404155
0024:Ret  ntdll.RtlAllocateHeap() retval=001b7ba8 ret=00404155
0024:Call KERNEL32.ReadFile(00000074,001b7ba8,0000355c,0033d4b0,00000000)
ret=00404174
0024:Ret  KERNEL32.ReadFile() retval=00000001 ret=00404174 
...
0024:Call KERNEL32.lstrlenW(code=c0000005 flags=0 addr=0xf75b21e1 ip=f75b21e1
tid=0024
0024:trace:seh:raise_exception  info[0]=00000000
0024:trace:seh:raise_exception  info[1]=001d0000
0024:trace:seh:raise_exception  eax=001d0000 ebx=f774f000 ecx=8a7a124c
edx=001b7ba8 esi=7b87d584 edi=0000355c
0024:trace:seh:raise_exception  ebp=0033d2d8 esp=0033d2a0 cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00010216
0024:trace:seh:call_stack_handlers calling handler at 0x7bc9dcbf code=c0000005
flags=0
0024:trace:seh:__regs_RtlUnwind code=c0000005 flags=2
0024:trace:seh:__regs_RtlUnwind calling handler at 0x7bc81a39 code=c0000005
flags=2
0024:trace:seh:__regs_RtlUnwind handler at 0x7bc81a39 returned 1 
...
--- snip ---

The installer reads a file '0x0409.ini' which contains UTF-16 text and converts
the content to ansi string.

--- snip ---
$ file 0x0409.ini 
0x0409.ini: Little-endian UTF-16 Unicode text, with CRLF, CR line terminators

$ ls -l 0x0409.ini 
-rw-rw-r--. 1 focht focht 13660 Mar 27  2008 0x0409.ini
--- snip ---

Strangely the read/conversion is done multiple times on the same file.
It works the first 3 times which shuffle the heap a bit.

The installer allocates filesize()+1 bytes with HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY, size).

Before ReadFile() on buffer:

NOTE: I dumped the leading/trailing bytes to show the heap block metadata, see
'USE' and 'FREE' magic.

--- snip ---
Address   Hex dump                                          ASCII
$-0x10    00 00 00 00|00 00 00 00|60 35 00 00|55 53 45 03|         USE
$         00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00|
$+0x10    00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00|
...
$+0x3550  00 00 00 00|00 00 00 00|00 00 00 00|00 73 6B 00|
$+0x3560  61 0C 0B 00|46 52 45 45|88 00 11 00|28 01 11 00|    FREE
--- snip ---

You can already spot the problem here: '00 73 6B 00' -> the first byte was
zero-init from HEAP_ZERO_MEMORY. The rest are left-over from previous use of
the block (alloc -> free -> alloc).

After ReadFile() of 13660 (0x355C) bytes on buffer:

BOM at beginning, followed by actual UTF-16 data.

--- snip ---
Address   Hex dump                                         ASCII
$-10      00 00 00 00|00 00 00 00|60 35 00 00|55 53 45 03|         USE
$         FF FE 0D 00|0A 00 5B 00|30 00 78 00|30 00 34 00|     [ 0 x 0 4
$+10      30 00 39 00|5D 00 0D 00|0A 00 54 00|49 00 54 00| 0 9 ] 
...
$+0x3550  69 00 65 00|64 00 29 00|0D 00 0A 00|00 73 6B 00|
$+0x3560  61 0C 0B 00|46 52 45 45|88 00 11 00|28 01 11 00|    FREE
--- snip ---

The installer calls lstrlenW() on the buffer, uses the length information to
allocate a new, stack based buffer and then calls WideCharToMultiByte().

lstrlenW() triggers a page fault in unmapped area in search of wide-character
NULL terminator because the adjacent block which is marked "FREE" contains
garbage until the end of mapping.

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list