TortoiseGit windows (at least the log viewer and the diff view) crashes when receiving an unexpected message
This is somewhat obscure and require some very specific circumstances to occur. But, I'd think that making the message handler a bit more robust would be beneficial also in other situations.
In short, I'm working on a NSIS plugin and while testing I found a bug in the "boilerplate code" used for such plugins. It has a function a plugin can call that will log a string to the NSIS installer's "details" output:
procedure LogMessage(Msg : NSISTString);
var
ItemCount : Integer;
item: TLV_ITEM;
begin
if g_hwndList = 0 then exit;
FillChar(item, sizeof(item), 0);
ItemCount := SendMessage(g_hwndList, LVM_GETITEMCOUNT, 0, 0);
item.iItem := ItemCount;
item.mask := LVIF_TEXT;
item.pszText := NSISPTChar(Msg);
ListView_InsertItem(g_hwndList, item);
ListView_EnsureVisible(g_hwndList, ItemCount, not 0);
end;
The problem turns out to be how if figures out g_hwndList
, which is in another part of the code:
g_hwndList := FindWindowEx(FindWindowEx(g_hwndParent, 0, '#32770', nil), 0,'SysListView32', nil);
I'm no expert at Windows window handling, but the problem manifests itself when there is no "parent window" (g_hwndParent == 0
). According to the Windows API documentation, using null (or 0 apparently) for hWndParent
makes FindWindowEx
search all the windows on the desktop. It seems that the code searches for a predefined "atom" with #32770
. I can only assume that this is some kind of hard-coded ID that NSIS windows use - and it seems that so does TortoiseGit. Because, consistently, this call returns one of TortoiseGit's windows if one is open. Otherwise in returns 0
.
What happens next is that my test code believe that is has found the control that it wants to send the log message to, and it fires a SendMessage
to one of TortoiseGit'a windows which then crashes. They crash in turn, one windows for each such call until I have no TortoiseGit windows left.
Even though it's definitely a bug on my part that the code searches the desktop, and I will have to address that, I would think that TortoiseGit should be able to handle "unsolicited messages" without crashing. I've uploaded a crash report to drdump with ID 125004194
if that is of any interest. Also, it reports the following stack trace:
comctl32!Ordinal392+0xac46
comctl32!GetWindowSubclass+0x7a7
comctl32!Ordinal395+0x3cdc
comctl32!Ordinal395+0x324f
user32!CallWindowProcW+0x3f8
user32!CallWindowProcW+0x8e
comctl32!DefSubclassProc+0x14a
comctl32!DSA_Create+0x1809
comctl32!DefSubclassProc+0x14a
comctl32!DSA_Create+0x1927
user32!CallWindowProcW+0x3f8
user32!CallWindowProcW+0x8e
mfc140u+0x29718f
mfc140u+0x29888e
mfc140u+0x29610e
mfc140u+0x2964d4
mfc140u+0x139579
user32!CallWindowProcW+0x3f8
user32!DispatchMessageW+0x39c
user32!SendMessageTimeoutW+0x143
ntdll!KiUserCallbackDispatcher+0x24
win32u!NtUserGetMessage+0x14
user32!GetMessageW+0x2e
mfc140u+0x27eac7
mfc140u+0x29d027
mfc140u+0x211acf
mfc140u+0x211efc
tortoisegitproc!LogCommand::Execute+0x7d7
tortoisegitproc!CTortoiseProcApp::InitInstance+0x2011
mfc140u+0x2b23c4
tortoisegitproc!__scrt_common_main_seh+0x106
kernel32!BaseThreadInitThunk+0x14
ntdll!RtlUserThreadStart+0x21
What steps will reproduce the problem?
Reproducing this is obviously not straight forward, so I've included an executable (test.exe
) which triggers it. Since building this executable requires several different tools, I haven't included full build instructions, but I've included "my part" of the source code. NSIS is used to build the executable, so the makensis
source could would also have to be reviewed to get the full picture. Regardless I can guarantee that it does nothing nefarious - what it does is that it searches the registry and some environment variables for Java installations (which is what the plugin is intended to do). If you don't trust running it, you could run it on a VM (if extra paranoid, take a snapshot first, and then roll it back after).
What is the expected output? What do you see instead?
I expect TortoiseGit to remain unaffected. Instead it crashes.
What version of TortoiseGit and Git are you using? On what operating system?
2.15.0, Windows 10.