http://bugs.winehq.org/show_bug.cgi?id=33525
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |Installer Status|UNCONFIRMED |NEW CC| |focht@gmx.net Component|-unknown |fusion Summary|Spices decompiler crashes |Spices.Decompiler v.5.4.8.0 |when installing |(.Net Decompiler) installer | |crashes Ever Confirmed|0 |1
--- Comment #2 from Anastasius Focht focht@gmx.net 2013-05-04 18:30:01 CDT --- Hello folks,
confirming. The problem is how Wine's fusion parses the CLR MetaData stream header table for the "NineRays.FlyGrid.dll" assembly. Incorrect calculation of string heap offset/rva leads to the crash.
--- snip --- Unhandled exception: page fault on read access to 0x00004993 in 32-bit code (0x7b85085c). Register dump: CS:0023 SS:002b DS:002b ES:002b FS:0063 GS:006b EIP:7b85085c ESP:0033f370 EBP:0033f3f8 EFLAGS:00010286( R- -- I S - -P- ) EAX:00000000 EBX:7b8b96b0 ECX:ffffffff EDX:00004993 ESI:0033f740 EDI:00004993 Stack dump: 0x0033f370: 7b8b96b0 0033f3e0 0033f3c8 7b8533e0 0x0033f380: 00000409 40000000 00525184 00000001 0x0033f390: f738879a 00000004 ffffffff ffffffff 0x0033f3a0: 00000000 00000000 00000000 ffffffff 0x0033f3b0: 00000002 7ffdf000 00000000 0033f3e0 0x0033f3c0: f738ba24 7ffdf000 0033f418 f7385d48 000c: sel=0067 base=00000000 limit=00000000 32-bit r-x Backtrace: =>0 0x7b85085c MultiByteToWideChar+0x69(page=0, flags=0, src=*** invalid address 0x4993 ***, srclen=0xffffffff, dst=0x0(nil), dstlen=0) [/home/focht/projects/wine/wine-git/dlls/kernel32/locale.c:1928] in kernel32 (0x0033f3f8) 1 0xf73861b2 assembly_dup_str+0x48(assembly=0xb3aab0, index=0x4993) [/home/focht/projects/wine/wine-git/dlls/fusion/assembly.c:719] in fusion (0x0033f438) 2 0xf73862b3 assembly_get_name+0x88(assembly=0xb3aab0, name=0x33f6b4) [/home/focht/projects/wine/wine-git/dlls/fusion/assembly.c:747] in fusion (0x0033f468) 3 0xf7380230 IAssemblyCacheImpl_InstallAssembly+0x1c8(iface=<couldn't compute location>, dwFlags=<couldn't compute location>, pszManifestFilePath=<couldn't compute location>, pRefData=<couldn't compute location>) [/home/focht/projects/wine/wine-git/dlls/fusion/asmcache.c:442] in fusion (0x0033f728) 4 0x7eca385c msi_install_assembly+0x1dc(package=0x140ff0, comp=0x1a5c90) [/home/focht/projects/wine/wine-build32/dlls/msi/../../include/fusion.h:266] in msi (0x0033f7a8) 5 0x7ecc86d0 ACTION_InstallFiles+0x566(package=0x140ff0) [/home/focht/projects/wine/wine-git/dlls/msi/files.c:407] in msi (0x0033f838) ... --- snip ---
Source: http://source.winehq.org/git/wine.git/blob/328383d4ebd0da48b64c1d627894c7859...
--- snip --- 561 static HRESULT parse_clr_metadata(ASSEMBLY *assembly) 562 { 563 METADATASTREAMHDR *streamhdr; 564 ULONG rva, i, ofs; 565 LPSTR stream; 566 HRESULT hr; 567 DWORD hdrsz; 568 BYTE *ptr; 569 570 hr = parse_metadata_header(assembly, &hdrsz); 571 if (FAILED(hr)) 572 return hr; 573 574 rva = assembly->corhdr->MetaData.VirtualAddress; 575 ptr = ImageRvaToVa(assembly->nthdr, assembly->data, rva + hdrsz, NULL); 576 if (!ptr) 577 return E_FAIL; 578 579 for (i = 0; i < assembly->metadatahdr->Streams; i++) 580 { 581 streamhdr = (METADATASTREAMHDR *)ptr; 582 ofs = rva_to_offset(assembly->nthdr, rva + streamhdr->Offset); 583 584 ptr += sizeof(METADATASTREAMHDR); 585 stream = (LPSTR)ptr; 586 587 if (!lstrcmpA(stream, "#~")) 588 { 589 hr = parse_clr_tables(assembly, ofs); 590 if (FAILED(hr)) 591 return hr; 592 } 593 else if (!lstrcmpA(stream, "#Strings") || !lstrcmpA(stream, "Strings")) 594 assembly->strings = assembly_data_offset(assembly, ofs); 595 else if (!lstrcmpA(stream, "#Blob") || !lstrcmpA(stream, "Blob")) 596 assembly->blobs = assembly_data_offset(assembly, ofs); 597 598 ptr += lstrlenA(stream) + 1; 599 ptr = (BYTE *)(((UINT_PTR)ptr + 3) & ~3); /* align on DWORD boundary */ 600 } 601 602 return S_OK; 603 } --- snip ---
Line 599 ought to DWORD-align to the next stream header.
Microsoft's Metadata/CLR specifications says:
--- quote --- Name of the stream as null-terminated variable length array of ASCII characters, padded to the next 4-byte boundary with \0 characters. The name is limited to 32 characters. --- quote ---
Actually the 4-byte boundary counting from the start offset of the "Name" member is meant here, not the alignment on overall offset/virtual address in PE image.
My hand sketched/calculated MetaData steam header table for "NineRays.FlyGrid.dll" assembly (unit = file offset bytes):
|dword1|dword2|...
--- snip --- <stream1> 0x45146: offset = 0x6C (DWORD) 0x4514A: size = 0x1CE18 (DWORD) 0x4514E: name = "#~" (len=2) |#,~,<null>,<pad>| <stream2> 0x45152: offset = 0x1CE84 (DWORD) 0x45156: size = 0x8E6E (DWORD) 0x4515A: name = "#Strings" (len=8) |#,S,t,r|i,n,g,s|<null>,<pad>,<pad>,<pad>| <stream3> 0x45166: offset = 0x25CF2 (DWORD) 0x4516A: size = 0x122C (DWORD) 0x4516E: name = "#US" (len=3) |#,U,S,<null>| <stream4> 0x45172: ... --- snip ---
Wine calculates the start of stream2 to 0x45154 (4-byte boundary overall offset). The correct offset should be 0x45152 (4-byte boundary within "Name" member).
$ du -sh Spices.Evaluation.msi 6.6M Spices.Evaluation.msi
$ sha1sum Spices.Evaluation.msi 5e37c658f607991c32ea6a4b66dc820d99ab1237 Spices.Evaluation.msi
$ wine --version wine-1.5.29-122-g865d53d
Regards