[Bug 38329] 64-bit Double Commander 0.6.x hangs on startup due to incorrect vectored handler struct layout

WineHQ Bugzilla wine-bugs at winehq.org
Fri Oct 29 08:41:25 CDT 2021


https://bugs.winehq.org/show_bug.cgi?id=38329

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
                 CC|                            |focht at gmx.net
          Component|-unknown                    |ntdll
           Keywords|                            |download
     Ever confirmed|0                           |1
                URL|https://sourceforge.net/pro |https://web.archive.org/web
                   |jects/doublecmd/files/DC%20 |/20211029121233/https://mas
                   |for%20Windows%2064%20bit/   |ter.dl.sourceforge.net/proj
                   |                            |ect/doublecmd/DC%20for%20Wi
                   |                            |ndows%2064%20bit/Double%20C
                   |                            |ommander%200.6.6%20beta/dou
                   |                            |blecmd-0.6.6.x86_64-win64.e
                   |                            |xe?viasf=1
            Summary|64-bit Double Commander     |64-bit Double Commander
                   |hangs                       |0.6.x hangs on startup due
                   |                            |to incorrect vectored
                   |                            |handler struct layout

--- Comment #5 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

confirming, still present.

Stable download link via Internet Archive:

https://web.archive.org/web/20211029121233/https://master.dl.sourceforge.net/project/doublecmd/DC%20for%20Windows%2064%20bit/Double%20Commander%200.6.6%20beta/doublecmd-0.6.6.x86_64-win64.exe?viasf=1

Trace log:

--- snip ---
$ pwd
/home/focht/.wine/drive_c/Program Files/Double Commander

$ WINEDEBUG=+seh,+relay,+server,+loaddll wine ./doublecmd.exe >>log.txt 2>&1
...
0104:Starting thread proc 00000001000176D0 (arg=0000000067FF0000)
0104:Call KERNEL32.BaseThreadInitThunk(00000000,1000176d0,67ff0000)
ret=7bc57752
0104:Call ntdll.RtlAddVectoredExceptionHandler(00000001,100017470)
ret=1000176c5
0104:Ret  ntdll.RtlAddVectoredExceptionHandler() retval=010a71b0 ret=1000176c5 
...
0104:Call ntdll.RtlAddVectoredExceptionHandler(00000001,100017f80)
ret=10001806e
0104:Ret  ntdll.RtlAddVectoredExceptionHandler() retval=010adcb0 ret=10001806e
<hangs>
--- snip ---

Debugging reveals the reason:

--- snip ---
010001803E | add byte ptr ds:[rax],al                      |
0100018040 | sub rsp,38                                    |
0100018044 | mov qword ptr ss:[rsp+20],rbx                 |
0100018049 | mov qword ptr ss:[rsp+28],rsi                 |
010001804E | lea rcx,qword ptr ds:[100017470]              | 
0100018055 | call <JMP.&RtlEncodePointer>                  |
010001805A | mov rbx,rax                                   |
010001805D | lea rdx,qword ptr ds:[100017F80]              | handler
0100018064 | mov ecx,1                                     | First = true
0100018069 | call <JMP.&RtlAddVectoredExceptionHandler>    |
010001806E | mov qword ptr ds:[1005C1350],rax              |
0100018075 | mov rax,qword ptr ds:[1005C1350]              |
010001807C | mov rsi,qword ptr ds:[rax]                    | entry.next
010001807F | nop                                           |
loop:
0100018080 | mov rax,qword ptr ds:[rsi+18]                 | handler->func
0100018084 | cmp rax,rbx                                   | found the handler? 
0100018087 | jne doublecmd.100018093                       |
0100018089 | mov rcx,rsi                                   |
010001808C | call <JMP.&RtlRemoveVectoredExceptionHandler> |
0100018091 | jmp doublecmd.10001809E                       |
0100018093 | mov rsi,qword ptr ds:[rsi]                    | entry.next
0100018096 | mov rax,rsi                                   |
0100018099 | test rax,rax                                  | no more entry?
(bug)
010001809C | jne doublecmd.100018080                       |
010001809E | mov rbx,qword ptr ss:[rsp+20]                 |
01000180A3 | mov rsi,qword ptr ss:[rsp+28]                 |
01000180A8 | add rsp,38                                    |
01000180AC | ret   
...
01000180E0 | sub rsp,28                                    |
01000180E4 | call doublecmd.100018040                      |
01000180E9 | add rsp,28                                    |
01000180ED | ret                                           |
--- snip ---

--- snip ---
$ ==> 0000000001066B80  00000000010666F0  ; entry.next
$+8   0000000001066B88  000000007BC81288  ; entry.prev 
$+10  0000000001066B90  F83852926C3391AB  ; handler->func
                                          ; = RtlEncodePointer( func )
$+18  0000000001066B98  0033006500000001  ; handler->count 
--- snip ---

--- snip ---
ntdll.vectored_exception_handlers:
000000007BC81288 0000000001066B80
000000007BC81290 00000000010666F0 ; &vectored_exception_handlers
--- snip ---

The code wants to find a specific vectored handler which already has been
installed in early startup phase. It can't find it because Wine's
VECTORED_HANDLER structure layout isn't correct. Due to an exit condition bug
(list entry/node = nil) in app code, it loops forever.

Wine source:

https://source.winehq.org/git/wine.git/blob/e5f7a73c83a2b50db27c084b7b913a371fa1d4bd:/dlls/ntdll/exception.c#l42

--- snip ---
  42 typedef struct
  43 {
  44     struct list                 entry;
  45     PVECTORED_EXCEPTION_HANDLER func;
  46     ULONG                       count;
  47 } VECTORED_HANDLER;
--- snip ---

If you swap func and count members it will work.

App source code just for reference. I didn't use it for analysis to not spoil
fun.

https://github.com/doublecmd/doublecmd/blob/master/src/platform/win/uexceptionhandlerfix.pas#L115

--- snip ---
type
  PVectoredExceptionNode = ^TVectoredExceptionNode;
  TVectoredExceptionNode = record
    m_pNextNode: PVectoredExceptionNode;
    m_pPreviousNode: PVectoredExceptionNode;
    m_Unknown: Pointer;
    m_pfnVectoredHandler: Pointer;
  end;
--- snip ---

https://github.com/doublecmd/doublecmd/blob/master/src/platform/win/uexceptionhandlerfix.pas#L195

--- snip ---
procedure InstallExceptionHandler;
var
  HandlerAddress: Pointer;
  Node: PVectoredExceptionNode;
begin
  // Get Free Pascal exception handler encoded address
  HandlerAddress := RtlEncodePointer(@syswin64_x86_64_exception_handler);
  VectoredExceptionHandler := AddVectoredExceptionHandler(1,
@ProcessException);
  // Find Free Pascal exception handler and remove it
  Node:= VectoredExceptionHandler^.m_pNextNode;
  repeat
    if (Node^.m_pfnVectoredHandler = HandlerAddress) then
    begin
      RemoveVectoredExceptionHandler(Node);
      Break;
    end;
    Node := Node^.m_pNextNode;
  until (Node = nil);
end;
--- snip ---

ProtectionID scan:

--- snip ---
-=[ ProtectionID v0.6.9.0 DECEMBER]=-
(c) 2003-2017 CDKiLLER & TippeX
Build 24/12/17-21:05:42
Ready...
Scanning -> C:\Program Files\Double Commander\doublecmd.exe
File Type : 64-Bit Exe (Subsystem : Win GUI / 2), Size : 9986579 (0986213h)
Byte(s) | Machine: 0x8664 (AMD64)
Compilation TimeStamp : 0x00000000 -> Thu 01st Jan 1970 00:00:00 (GMT)
-> File has 19 (013h) bytes of appended data starting at offset 0986200h
[LoadConfig] CodeIntegrity -> Flags 0xAA60 | Catalog 0x46 (70) | Catalog Offset
0x2000001 | Reserved 0x46AB40
[LoadConfig] GuardAddressTakenIatEntryTable 0x46AC88:02000011 | Count
0x46AE9C02000011 (463222033554449)
[LoadConfig] GuardLongJumpTargetTable 0x46AF38:08000011 | Count
0x46AFE008000011 (4632544134217745)
[LoadConfig] HybridMetadataPointer 0x46A66C:08000011 | DynamicValueRelocTable
0x8000011:0046B0A8
[LoadConfig] FailFastIndirectProc 0x8000011:0046B264 | FailFastPointer
0x8000011:0046B2FC
[LoadConfig] UnknownZero1 0x8000011  46B448
[File Heuristics] -> Flag #1 : 00000000000001011100000000010100 (0x0005C014)
[Entrypoint Section Entropy] : 5.72 (section #0) ".text   " | Size : 0x5BCDB0
(6016432) byte(s)
[DllCharacteristics] -> Flag : (0x0000) -> NONE
[SectionCount] 7 (0x7) | ImageSize 0x998000 (10059776) byte(s)
[VersionInfo] Product Name : Double Commander
[VersionInfo] File Description : Double Commander is a cross platform open
source file manager with two panels side by side
[VersionInfo] File Version : 0.6.6.0
[VersionInfo] Internal Name : DOUBLECMD
[VersionInfo] Legal Copyrights : Copyright (C) 2006-2015 Alexander Koblov
[ModuleReport] [IAT] Modules -> advapi32.dll | comctl32.dll | comdlg32.dll |
gdi32.dll | imm32.dll | kernel32.dll | mpr.dll | msimg32.dll | netapi32.dll |
ntdll.dll | ole32.dll | oleaut32.dll | shell32.dll | shlwapi.dll | user32.dll |
version.dll | winmm.dll
[!] File appears to have no protection or is using an unknown protection
- Scan Took : 1.76 Second(s) [000000784h (1924) tick(s)] [234 of 580 scan(s)
done]
--- snip ---

$ sha1sum doublecmd-0.6.6.x86_64-win64.exe 
31b85211f1fd737b8773be35e102788e357273ce  doublecmd-0.6.6.x86_64-win64.exe

$ du -sh doublecmd-0.6.6.x86_64-win64.exe 
9.2M    doublecmd-0.6.6.x86_64-win64.exe

$ wine --version
wine-6.20-195-ge5f7a73c83a

Regards

-- 
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