http://bugs.winehq.org/show_bug.cgi?id=21624
Summary: MJ12node.exe crashes with StackOverflowException Product: Wine Version: 1.1.38 Platform: x86 URL: http://www.majestic12.co.uk/projects/dsearch/download. php OS/Version: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: -unknown AssignedTo: wine-bugs@winehq.org ReportedBy: refic@psimerion.org
Created an attachment (id=26100) --> (http://bugs.winehq.org/attachment.cgi?id=26100) console output
When I try to run MJ12node.exe (Majestic-12 distributed search engine client) it starts but crashes immediately with "Process is terminated due to StackOverflowException". It's a .NET 2.0 application so I installed dotnet20 via winetricks. The app can be downloaded from the URL provided but I can surely do more testing myself if needed.
http://bugs.winehq.org/show_bug.cgi?id=21624
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |focht@gmx.net
--- Comment #1 from Anastasius Focht focht@gmx.net 2010-02-07 08:21:17 --- Hello,
--- snip --- fixme:ntoskrnl:KeInitializeTimerEx stub: 0x131288 0 ... --- snip ---
it seems you installed the app into a tainted WINEPREFIX which can cause all kinds of errors.
Just use a new/clean WINEPREFIX for your .NET app (see wine wiki/appdb if unsure what that means)
You need 'winetricks dotnet20 corefonts' steps.
'corefonts' is needed because the app requires arial font (despite the app saying 'ignored global error'):
--- snip --- Ignored global app error: System.ArgumentException: Font 'Arial' cannot be found. at System.Drawing.FontFamily.CreateFontFamily(String name, FontCollection fontCollection) at System.Drawing.FontFamily..ctor(String name) at NPlot.PlotSurface2D.Init() at NPlot.Windows.PlotSurface2D..ctor() at MJ12node.frmMain.InitializeComponent() at MJ12node.frmMain..ctor(String[] p_args) at MJ12node.frmMain.Main(String[] args) --- snip ---
You might also want to set gdiplus to "native then builtin" to prevent serious font drawing ugliness.
Regards
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #2 from Kari refic@psimerion.org 2010-02-07 09:35:15 --- Hi,
Thanks for your tips, however the result is still the same after using a clean WINEPREFIX. The only thing that's different now is that there's no "fixme:ntoskrnl:KeInitializeTimerEx stub: 0x131288 0" at the start, but it still gives a StackOverflowException.
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #3 from Anastasius Focht focht@gmx.net 2010-02-07 10:26:29 --- Hello,
I'm unable to reproduce it ... works fine here. Please provide a full trace log:
WINEDEBUG=+tid,+seh,+relay wine MJ12node.exe &> log.txt
and attach to this bug. If the log file is too large for attachment, compress it with 'bzip2 -9' and attach.
Regards
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #4 from Kari refic@psimerion.org 2010-02-07 11:26:01 --- Here's the log: http://refic.psimerion.org/log.txt.bz2 - it was a bit too big to be attached here.
I tried recompiling Wine and a new wineprefix (just in case..) but no difference.
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #5 from Anastasius Focht focht@gmx.net 2010-02-07 11:55:04 --- Hello,
looks like heap corruption leading to recursive exception -> stack overflow. Unfortunately at the location of the first suspect exception there are interleaving/corrupted lines due to multithreading... can you rerun the program like this:
(remove any log.txt before that)
WINEDEBUG=+tid,+seh,+relay wine MJ12node.exe >>log.txt 2>&1
and attach/provide new log.
Regards
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #6 from Kari refic@psimerion.org 2010-02-07 12:06:29 --- Here you go: http://refic.psimerion.org/log_2.txt.bz2
It actually went a bit further after starting, but crashed when I tried to click a button from the gui.
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #7 from Anastasius Focht focht@gmx.net 2010-02-07 12:35:43 --- Hello,
--- quote --- It actually went a bit further after starting, but crashed when I tried to click a button from the gui. --- quote ---
Well depending on threading/timing and location of corrupted heap blocks it might not crash at the same place. Can you rerun the app with heap checking enabled? Beware, the log might get large and app startup/responsiveness will be very slow:
(remove any log.txt before that)
WINEDEBUG=+tid,+seh,+relay,+heap wine MJ12node.exe >>log.txt 2>&1
and attach/provide new log.
Regards
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #8 from Kari refic@psimerion.org 2010-02-07 12:47:22 --- Sure: http://refic.psimerion.org/log_3.txt.bz2
http://bugs.winehq.org/show_bug.cgi?id=21624
Austin English austinenglish@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #9 from Anastasius Focht focht@gmx.net 2010-02-07 15:16:26 --- Hello,
thanks for the logs. My instinct for interesting bugs did not let me down ;-)
The problem is most likely buried within iphlpapi.GetNetworkParams() and use of dns resolver API.
Query the buffer size:
--- snip --- 002d:Call iphlpapi.GetNetworkParams(00000000,0457df5c) ret=03994f7e 002d:Ret iphlpapi.GetNetworkParams() retval=0000006f ret=03994f7e ... 002d:trace:heap:RtlAllocateHeap (0x110000,70000062,00000270): returning 0x400a138 ... --- snip ---
Fill the network/dns info into provided buffer:
--- snip --- 002d:Call iphlpapi.GetNetworkParams(0400a138,0457df5c) ret=03994f7e ... 002d:Call advapi32.RegQueryValueExA(000002e4,7e058bb9 "ScopeID",00000000,00000000,0400a270,0457dde4) ret=7e053c8b 002d:Ret advapi32.RegQueryValueExA() retval=00000002 ret=7e053c8b ... 002d:Ret iphlpapi.GetNetworkParams() retval=00000000 ret=03994f7e --- snip ---
Relevant structures to calculate sizes (needed later):
--- snip include/iptypes.h --- typedef struct { char String[4 * 4]; } IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
typedef struct _IP_ADDR_STRING { struct _IP_ADDR_STRING* Next; IP_ADDRESS_STRING IpAddress; IP_MASK_STRING IpMask; DWORD Context; } IP_ADDR_STRING, *PIP_ADDR_STRING;
...
typedef struct { char HostName[MAX_HOSTNAME_LEN + 4] ; char DomainName[MAX_DOMAIN_NAME_LEN + 4]; PIP_ADDR_STRING CurrentDnsServer; IP_ADDR_STRING DnsServerList; UINT NodeType; char ScopeId[MAX_SCOPE_ID_LEN + 4]; UINT EnableRouting; UINT EnableProxy; UINT EnableDns; } FIXED_INFO, *PFIXED_INFO; --- snip include/iptypes.h ---
Sizes:
128+4 HostName 128+4 DomainName 4 CurrentDnsServer 40 DnsServerList 4 NodeType 256+4 ScopeId 4 EnableRouting 4 EnableProxy 4 EnableDns
Sum: 584 bytes -> 0x248 hex bytes
0x270 bytes from previous iphlpapi.GetNetworkParams() calls:
sizeof(FIXED_INFO) + sizeof(IP_ADDR_STRING) = two dns server entries. Additional dns server entries (_res.nscount > 1) are appended to struct FIXED_INFO.
Some time later (on different thread 0x3d):
--- snip --- 003d:Call iphlpapi.GetNetworkParams(00000000,0b7ddc50) ret=03994f7e 003d:Ret iphlpapi.GetNetworkParams() retval=0000006f ret=03994f7e ... 003d:trace:heap:RtlAllocateHeap (0x110000,70000062,00000248): returning 0x4009aa0 ... 003d:Call iphlpapi.GetNetworkParams(04009aa0,0b7ddc50) ret=03994f7e ... 003d:Call KERNEL32.GetComputerNameExA(00000001,04009aa0,0b7ddadc) ret=7e053b75 ... 003d:Ret KERNEL32.GetComputerNameExA() retval=00000001 ret=7e053b75 003d:Call KERNEL32.GetComputerNameExA(00000002,04009b24,0b7ddadc) ret=7e053b9c ... 003d:Ret KERNEL32.GetComputerNameExA() retval=00000001 ret=7e053b9c 003d:Call advapi32.RegOpenKeyExA(80000002,7e058870 "SYSTEM\CurrentControlSet\Services\VxD\MSTCP",00000000,00020019,0b7ddad8) ret=7e053c43 003d:Ret advapi32.RegOpenKeyExA() retval=00000000 ret=7e053c43 003d:Call advapi32.RegQueryValueExA(000003b4,7e058bb9 "ScopeID",00000000,00000000,04009bd8,0b7ddad4) ret=7e053c8b 0009:err:heap:HEAP_ValidateInUseArena Heap 0x110000: block 0x4009aa0 tail overwritten at 0x4009ce8 (byte 0/8 == 0x00) 003d:Ret advapi32.RegQueryValueExA() retval=00000002 ret=7e053c8b --- snip ---
This is where wine's heap detector raises its hand first time because the FIXED_INFO buffer was written past the end.
If you look closely you notice this time the GetNetworkParams() query for buffer size returned only 0x248 bytes - which is just sizeof(FIXED_INFO) = 1 dns server entry?!
Looking at the corresponding code:
--- snip dlls/iphlpapi/ --- DWORD WINAPI GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen) { DWORD ret, size; LONG regReturn; HKEY hKey;
TRACE("pFixedInfo %p, pOutBufLen %p\n", pFixedInfo, pOutBufLen); if (!pOutBufLen) return ERROR_INVALID_PARAMETER;
initialise_resolver(); size = sizeof(FIXED_INFO) + (_res.nscount > 0 ? (_res.nscount - 1) * sizeof(IP_ADDR_STRING) : 0); if (!pFixedInfo || *pOutBufLen < size) { *pOutBufLen = size; return ERROR_BUFFER_OVERFLOW; }
memset(pFixedInfo, 0, size); size = sizeof(pFixedInfo->HostName); GetComputerNameExA(ComputerNameDnsHostname, pFixedInfo->HostName, &size); size = sizeof(pFixedInfo->DomainName); GetComputerNameExA(ComputerNameDnsDomain, pFixedInfo->DomainName, &size); if (_res.nscount > 0) { PIP_ADDR_STRING ptr; int i;
for (i = 0, ptr = &pFixedInfo->DnsServerList; i < _res.nscount && ptr; i++, ptr = ptr->Next) { toIPAddressString(_res.nsaddr_list[i].sin_addr.s_addr, ptr->IpAddress.String); if (i == _res.nscount - 1) ptr->Next = NULL; else if (i == 0) ptr->Next = (PIP_ADDR_STRING)((LPBYTE)pFixedInfo + sizeof(FIXED_INFO)); else ptr->Next = (PIP_ADDR_STRING)((PBYTE)ptr + sizeof(IP_ADDR_STRING)); } } pFixedInfo->NodeType = HYBRID_NODETYPE; regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\VxD\MSTCP", 0, KEY_READ, &hKey); if (regReturn != ERROR_SUCCESS) regReturn = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Services\NetBT\Parameters", 0, KEY_READ, &hKey); if (regReturn == ERROR_SUCCESS) { DWORD size = sizeof(pFixedInfo->ScopeId);
RegQueryValueExA(hKey, "ScopeID", NULL, NULL, (LPBYTE)pFixedInfo->ScopeId, &size); RegCloseKey(hKey); } ... --- snip dlls/iphlpapi/ ---
The only code that is able to write past the FIXED_INFO buffer is the dns server entries list population loop. If for some reason "_res.nscount" changes between overall buffer size calculation and dns server entries list population it could be possible to corrupt nearby block.
Now the question is: who can change "_res.nscount"? The API that might be the culprit is GetComputerNameExA( ComputerNameDnsHostname, ...) which is called in between "_res.nscount" queries.
dlls/kernel32/computername.c: dns_hostname() -> dns_fqdn() -> gethostname() and dns_gethostbyname()/gethostbyname_r()
So this code path seems potentially harmful to GetNetworkParams() as it might change "_res" dns resolver struct members implicitly.
Again this is just my theory how the memory corruption might be caused. I could be wrong as I can't reproduce the problem on my machine. For testing you could place a consistency check, comparing "_res.nscount" before and after GetComputerNameExA().
Regards
http://bugs.winehq.org/show_bug.cgi?id=21624
Dan Kegel dank@kegel.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW CC| |dank@kegel.com Ever Confirmed|0 |1
--- Comment #10 from Dan Kegel dank@kegel.com 2010-02-07 23:55:06 --- yay heap checking!
To reproduce the error, add extra name servers to /etc/resolv.conf, e.g. nameserver 8.8.8.8 nameserver 8.8.4.4
It turns out _res is thread-specific in glibc, so _res is uninitialized on all but the thread that called res_init(). See http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/libc/resolv/README?rev=1...
I'll send a patch.
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #11 from Dan Kegel dank@kegel.com 2010-02-08 00:03:02 --- Patch sent, http://www.winehq.org/pipermail/wine-patches/2010-February/084662.html
http://bugs.winehq.org/show_bug.cgi?id=21624
--- Comment #12 from Kari refic@psimerion.org 2010-02-08 02:35:42 --- The patch works indeed. Thanks a lot both!
http://bugs.winehq.org/show_bug.cgi?id=21624
Juan Lang juan_lang@yahoo.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution| |FIXED
--- Comment #13 from Juan Lang juan_lang@yahoo.com 2010-02-08 14:09:15 --- Fixed by commit 22434f490a83d2a1f4c3721d95f9a7c78fd44ef1.
http://bugs.winehq.org/show_bug.cgi?id=21624
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #14 from Alexandre Julliard julliard@winehq.org 2010-02-19 12:32:32 --- Closing bugs fixed in 1.1.39.
http://bugs.winehq.org/show_bug.cgi?id=21624
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |22434f490a83d2a1f4c3721d95f | |9a7c78fd44ef1 Component|-unknown |iphlpapi