[Bug 13411] setup_exception_record stack overflow in Teach2000

wine-bugs at winehq.org wine-bugs at winehq.org
Thu Dec 18 17:11:15 CST 2008


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


Anastasius Focht <focht at gmx.net> changed:

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




--- Comment #3 from Anastasius Focht <focht at gmx.net>  2008-12-18 17:11:14 ---
Hello,

you only need a clean WINEPREFIX and msxml4 as prerequisite.

sh winetricks msxml4

---

The app is delphi 6/7 based, making heavy use of the TNT UnicodeControls
toolkit which adds unicode capability for the standard VCL controls.

The crash happens while destroying an MDI child form as outlined in steps from
comment #1

In the destroy message handler, the window/control text gets retrieved from
(subclassed) controls.

First, the text length is determined by sending WM_GETTEXTLENGTH message.
Then a buffer is allocated with determined length and lastly the control text
is captured into buffer.
Unfortunately that doesn't work out as expected ...

--- snip ---
...
0009:Call window proc 0xdf0d99
(hwnd=0x1011c,msg=WM_DESTROY,wp=00000000,lp=00000000)
0009:Call user32.SendMessageA(0001011c,0000000e,00000000,00000000) ret=004d1be0
0009:Call hook proc 0x580390 (id=WH_CALLWNDPROC,code=0,wp=00000001,lp=0032da94)
0009:Call user32.CallNextHookEx(00010046,00000000,00000001,0032da94)
ret=0058040d
0009:Ret  user32.CallNextHookEx() retval=00000000 ret=0058040d
0009:Ret  hook proc 0x580390 (id=WH_CALLWNDPROC,code=0,wp=00000001,lp=0032da94)
retval=00000000
0009:trace:msg:WINPROC_CallProcAtoW
(hwnd=0x1011c,msg=WM_GETTEXTLENGTH,wp=00000000,lp=00000000)
0009:Call window proc 0xdf0d8c
(hwnd=0x1011c,msg=WM_GETTEXTLENGTH,wp=00000000,lp=00000000)
0009:Call user32.CallWindowProcW(00df0d99,0001011c,0000000e,00000000,00000000)
ret=004d1851
0009:Call window proc 0xdf0d99
(hwnd=0x1011c,msg=WM_GETTEXTLENGTH,wp=00000000,lp=00000000)
0009:Ret  window proc 0xdf0d99
(hwnd=0x1011c,msg=WM_GETTEXTLENGTH,wp=00000000,lp=00000000) retval=00000000
0009:Ret  user32.CallWindowProcW() retval=00000000 ret=004d1851
0009:Ret  window proc 0xdf0d8c
(hwnd=0x1011c,msg=WM_GETTEXTLENGTH,wp=00000000,lp=00000000) retval=00000000
0009:Call window proc 0xdf0d8c
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc)
0009:Call user32.CallWindowProcW(00df0d99,0001011c,0000000d,00000001,0032d4fc)
ret=004d1851
0009:Call window proc 0xdf0d99
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc)
0009:Call user32.CallWindowProcA(00df0d7f,0001011c,0000000d,00000001,0032d4fc)
ret=00471ecc
0009:Call window proc 0xdf0d7f
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc)
0009:Call user32.CallWindowProcW(60650fb2,0001011c,0000000d,00000001,0032d4fc)
ret=004d1a55
0009:Call window proc 0x60650fb2
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc)
0009:Call user32.GetWindowLongW(0001011c,00000000) ret=60650fd7
0009:Ret  user32.GetWindowLongW() retval=001ca680 ret=60650fd7
0009:trace:statusbar:StatusWindowProc hwnd=0x1011c msg=d wparam=1 lparam=32d4fc
0009:trace:statusbar:STATUSBAR_WMGetText 
0009:Ret  window proc 0x60650fb2
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc) retval=ffffffff
0009:Ret  user32.CallWindowProcW() retval=ffffffff ret=004d1a55
0009:Ret  window proc 0xdf0d7f
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc) retval=ffffffff
0009:Ret  user32.CallWindowProcA() retval=ffffffff ret=00471ecc
0009:Ret  window proc 0xdf0d99
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc) retval=ffffffff
0009:Ret  user32.CallWindowProcW() retval=ffffffff ret=004d1851
0009:Ret  window proc 0xdf0d8c
(hwnd=0x1011c,msg=WM_GETTEXT,wp=00000001,lp=0032d4fc) retval=ffffffff
0009:Ret  user32.SendMessageA() retval=7fffffff ret=004d1be0
0009:trace:seh:raise_exception code=c0000005 flags=0 addr=0x40e5ed
0009:trace:seh:raise_exception  info[0]=00000001
0009:trace:seh:raise_exception  info[1]=00000000
0009:trace:seh:raise_exception  eax=00000000 ebx=80000004 ecx=00000000
edx=7fffffff esi=7fffffff edi=0032de08
0009:trace:seh:raise_exception  ebp=0032dd50 esp=0032dc10 cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00210246
...
0009:Call oleaut32.SysAllocStringLen(0032c658 L"Access violation at address
0040E5ED in module 'Teach2000.exe'. Write of address 00000000",00000059)
ret=00405cc0
--- snip ---

The user control exhibiting the problem: a TTntStatusBar statusbar (unicode)
control, subclassed from standard VCL one

--- snip ---
0009:Call user32.CreateWindowExW(00000000,001b89c4
L"TTntStatusBar.UnicodeClass",00000000,44000001,00000000,00000246,000004e4,00000013,0002010e,00000000,00400000,00000000)
ret=00408e54
0009:trace:win:WIN_CreateWindowEx (null) L"TTntStatusBar.UnicodeClass"
ex=00000000 style=44000001 0,582 1252x19 parent=0x2010e menu=(nil)
inst=0x400000 params=(nil)
0009:trace:win:dump_window_styles style: WS_CHILD WS_CLIPSIBLINGS 00000001
0009:trace:win:dump_window_styles exstyle:
0009:trace:win:WIN_SetWindowLong 0x1011c -12 0 W 
--- snip ---

If you look at the return value from last SendMessage() call before the
exception, 0x7fffffff is returned.
This value ought to be the control text length which is obviously wrong.
The VCL allocator can't allocate such a huge amount of memory, resulting in
internal access violation.

The WM_GETTEXTLENGTH retrieval through default handlers in WINPROC_CallProcAtoW
is correct, the result (text length) has to be zero for this control.

But the following code is somewhat buggy...

Even with zero length determined, WM_GETTEXT gets called.
The (l)results from callback/SendMessage - which might be negative(!) - are
passed unchecked to RtlUnicodeToMultiByteSize() which happily calculates
incorrect length.
That's what this delphi app stumbles about.

--- dlls/user32/wndproc.c snip ---
LRESULT WINPROC_CallProcAtoW( winproc_callback_t callback, HWND hwnd, UINT msg,
WPARAM wParam,
                              LPARAM lParam, LRESULT *result, void *arg, enum
wm_char_mapping mapping )
{

...
   case WM_GETTEXTLENGTH:
   case CB_GETLBTEXTLEN:
   case LB_GETTEXTLEN:
        ret = callback( hwnd, msg, wParam, lParam, result, arg );
        if (*result >= 0)
        {
            WCHAR *ptr, buffer[512];
            LRESULT tmp;
            DWORD len = *result + 1;
            /* Determine respective GETTEXT message */
            UINT msgGetText = (msg == WM_GETTEXTLENGTH) ? WM_GETTEXT :
                              ((msg == CB_GETLBTEXTLEN) ? CB_GETLBTEXT :
LB_GETTEXT);
            /* wParam differs between the messages */
            WPARAM wp = (msg == WM_GETTEXTLENGTH) ? len : wParam;

            if (!(ptr = get_buffer( buffer, sizeof(buffer), len * sizeof(WCHAR)
))) break;

            if (callback == call_window_proc)  /* FIXME: hack */
                callback( hwnd, msgGetText, wp, (LPARAM)ptr, &tmp, arg );
            else
                tmp = SendMessageW( hwnd, msgGetText, wp, (LPARAM)ptr );
            RtlUnicodeToMultiByteSize( &len, ptr, tmp * sizeof(WCHAR) );
            *result = len;
            free_buffer( buffer, ptr );
        }
        break;

...
}
--- dlls/user32/wndproc.c snip ---

Either skip the text retrieval for length == 0 (whats the reason anyway?) or
check the return value from XX_GETTEXT before determining the byte buffer
length.

I already verified with a patch, the app doesn't crash then.

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