[Bug 22661] XMedia Recode crashes

wine-bugs at winehq.org wine-bugs at winehq.org
Wed Aug 18 08:13:34 CDT 2010


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


Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net




--- Comment #20 from Anastasius Focht <focht at gmx.net>  2010-08-18 08:13:32 ---
Hello,

interesting bug - though can't be fixed in Wine ;-)

Relevant app assembly snippet, annotated:

--- snip ---
0x004790b0: subl    $0x108,%esp
0x004790b6: movl    0x005168e0,%eax
0x004790bb: xorl    %esp,%eax
0x004790bd: movl    %eax,0x104(%esp)
0x004790c4: movl    0x15c(%esi),%ecx
0x004790ca: pushl    %ebx ; %ebx is zero on entry (value by chance, caller and
parent callers don't explicitly init it)
0x004790cb: pushl    $0x3714
0x004790d0: pushl    $0x104
0x004790d5: leal    0xc(%esp),%ebx
0x004790d9: call    0x0046dff0 ; load format string "Analysis %1.f %%"
0x004790de: pushl    $0x0 ; 1st (var) arg -> should be float (64 bit) but
instead only 32 bits are passed on stack
0x004790e0: movl    %ebx,%eax
0x004790e2: pushl    %eax ; format string (= dest buffer)
0x004790e3: movl    %ebx,%ecx
0x004790e5: pushl    %ecx ; dest buffer
0x004790e6: movl    $0x104,%eax ; register pass (max) buffer size in bytes arg
for next sprintf-like call
0x004790eb: call    0x00473310 ; get formatted string using sprintf() like app
logic
0x004790f0: addl    $12,%esp
0x004790f3: movl    %ebx,%edx
0x004790f5: pushl    %edx
...
0x00479120: movl    0x108(%esp),%ecx
0x00479127: popl    %ebx
0x00479128: xorl    %esp,%ecx
0x0047912a: call    0x004bcf66
0x0047912f: addl    $0x108,%esp
0x00479135: ret    
--- snip ---

The problem is that the 1st var argument to sprintf like function logic is
incorrectly passed as 32-bit integer when it should be passed as 64 bit float
(see format string).
Because only 32 bits are passed, the other "ghost" 32 bits come from existing
stack value which most likely happens to be zero on Windows (by chance!) and
non-zero on Wine.

That "0x004790ca: pushl    %ebx" actually "saves" the Windows side here.
Because %ebx is zero on function entry (by chance!), that stack location gets
zeroed where the "ghost" 32 bit part of float 64 bit value lives.

There is no way the compiler could have optimized %ebx value on a global level
like this, retaining ebx == 0 so long through several call chains (even dynamic
calls).
I traced some caller levels up but there is no explicit %ebx -> 0. There are
dynamic calls to window proc and the like.

The reason why this register is non-zero on (x86) Wine is the PIC code uses
this register to store the GOT (global offset table) address, hence it's not
zero at this point (still pointing to user32's _GLOBAL_OFFSET_TABLE_).

My guess is the app developer did something stupid like this:

sprintf( buf, "Analysis %1.f %%", 0);

but intended this:

sprintf( buf, "Analysis %1.f %%", 0.0);

The compiler should generate code like this for passing the "0.0" constant:

--- snip ---
fldz   
fstpl <arg_stack_loc>
--- snip ---

If you ask me -> not fixable in Wine.

Regards

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
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