[Bug 10417] New: OLEAUT32: crash if >128 methods in an interface

wine-bugs at winehq.org wine-bugs at winehq.org
Sun Nov 11 13:36:03 CST 2007


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

           Summary: OLEAUT32: crash if >128 methods in an interface
           Product: Wine
           Version: 0.9.49.
          Platform: Macintosh
        OS/Version: Mac OS X 10.5
            Status: UNCONFIRMED
          Severity: normal
          Priority: P1
         Component: wine-ole
        AssignedTo: wine-bugs at winehq.org
        ReportedBy: mjk at cardbox.com


This bug was encountered in build cxoffice-6.2.0rc1-2-g024be42 of Wine (part of
CrossOver Mac). The bug has been identified in the current source code at
http://source.winehq.org/source/dlls/oleaut32/tmarshal.c.

Using any marshaled interface with more than 128 methods causes a crash within
OLEAUT32 if any method at position >=128 is called. This was detected when
using Cardbox (http://www.cardbox.com) and is a SHOW-STOPPER because it makes
the use of VBScript macros impossible.

However, the bug is completely general and applies to any application at all
that has interfaces with large number of methods. It is quite possible that
many random OLE / COM - related bugs that have already been reported have this
bug as their underlying cause.

The version of Cardbox on which the bug was found is more recent than the one
currently available on the web site. If anyone wants to have a copy for
testing, together with instructions for reproducing the crash, please contact
me.

LOCATION OF THE BUG

The bug is in dlls/oleaut32/tmarshal.c. When constructing a proxy interface,
PSFacBuf_CreateProxy at line #1712 constructs the following proxy code for each
method:

 popl %eax
 pushl <nr>
 pushl %eax
 call xCall
 lret <n> (+4)

where <nr> is the position of the method in the list of methods: 0, 1, 2, and
so on.

The pushl <nr> instruction is defined by following code:

374     BYTE        pushlval; // set to 0x6a by line #1712
375     BYTE        nr;

The fact that the method position is a byte already limits the maximum size of
an interface to 256 methods, which is less than the 512-method limit of Windows
NT4.0 SP3, and the 1024-method limit of Windows 2000: see "MIDL2362" in
http://msdn2.microsoft.com/en-us/library/aa366756.aspx for details. Thus this
needs to be corrected in any case. The proxy code as it stands will call method
0 instead of method 256, method 1 instead of method 257, and so on, leading to
random behaviour and possible stack corruption.

The crash when method 128 is called has a different cause. The proxy for method
128 contains the instruction 6A 80, because the programmer thought that this
would push 00000080 onto the stack. In fact the PUSH instruction with opcode 6A
SIGN-EXTENDS its operand and does not zero-extend it. Thus the proxy for the
128th method pushes FFFFFF80 onto the stack before calling xCall. xCall
interprets this as a negative number (-128) and thus attempts to synthesize a
call not to method 128 but to a non-existent method -128. In the same way it
will call method -127 instead of method 129,... and so on.

SUGGESTED CORRECTION

The very simple correction to this bug, which is guaranteed to work, is to
alter line 375 to

375     DWORD        nr;

and line 1712 to

1712         xasm->pushlval  = 0x68;

which expects a 32-bit operand rather than an 8-bit one.

This will result in every proxy using 15 bytes per method instead of 12 bytes.
This does not seem an excessive price to pay for complete reliability in the
future: there will then be no limit to the number of methods that can be
supported.

ALTERNATIVE CORRECTIONS

If the 25% expansion in proxy size is considered unacceptable (it should not
really be: proxies are small) then there are several ways round the problem. An
increase to 256 methods could be achieved simply by adding a line at the very
beginning of xCall:

          method &= 0xff;

but this would HAVE to be accompanied by an explicit test for the method count
limit (now 256) in PSFacBuf_CreateProxy so that the attempt to create a proxy
with too methods would simply fail rather than (as now) generate a proxy that
will randomly crash the application.

Another approach would be to create dummy functions (in assembler) that would
add 128, 256, 384, 512, etc to the 'method' argument before forwarding it on to
xCall. In that case, method numbers after 127 would generate proxies that
called one of the variant xCalls instead of the original one. The programming
in PSFacBuf_CreateProxy would be relatively straightforward, and the dummy
functions would not need to do any stack manipulation: they would simply add an
offset to the DWORD at [ESP+8] and then JMP straight to the start of xCall.

This would *still* give a finite limit to the number of methods, but the limit
would be much larger. Again, good engineering practice dictates that
PSFacBuf_CreateProxy should report an error if it encounters a number of
methods beyond the number that it was designed to cope with.


-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list