Change: [Win32] don't allocate 192KiB of memory on the stack on crash (#11240)

Heap is out of the question, as it might be corrupted.
Allocating this much on stack is silly.

So instead, allocate virtual pages to write the information in.
This commit is contained in:
Patric Stout 2023-08-28 12:14:11 +02:00 committed by GitHub
parent de5e338a76
commit b0d7cfaa3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 36 deletions

View File

@ -433,7 +433,7 @@ static const wchar_t _crash_desc[] =
L"Please send crash.log, crash.dmp, and crash.sav to the developers.\n" L"Please send crash.log, crash.dmp, and crash.sav to the developers.\n"
L"This will greatly help debugging.\n\n" L"This will greatly help debugging.\n\n"
L"https://github.com/OpenTTD/OpenTTD/issues\n\n" L"https://github.com/OpenTTD/OpenTTD/issues\n\n"
L"%s"; L"%s\n%s\n%s\n%s\n";
static const wchar_t * const _expand_texts[] = {L"S&how report >>", L"&Hide report <<" }; static const wchar_t * const _expand_texts[] = {L"S&how report >>", L"&Hide report <<" };
@ -462,44 +462,51 @@ static INT_PTR CALLBACK CrashDialogFunc(HWND wnd, UINT msg, WPARAM wParam, LPARA
{ {
switch (msg) { switch (msg) {
case WM_INITDIALOG: { case WM_INITDIALOG: {
size_t crashlog_length = CrashLogWindows::current->crashlog.size() + 1;
/* Reserve extra space for LF to CRLF conversion. */
crashlog_length += std::count(CrashLogWindows::current->crashlog.begin(), CrashLogWindows::current->crashlog.end(), '\n');
const size_t filename_count = 4;
const size_t filename_buf_length = MAX_PATH + 1;
const size_t crash_desc_buf_length = lengthof(_crash_desc) + filename_buf_length * filename_count + 1;
/* We need to put the crash-log in a separate buffer because the default /* We need to put the crash-log in a separate buffer because the default
* buffer in MB_TO_WIDE is not large enough (512 chars) */ * buffer in MB_TO_WIDE is not large enough (512 chars).
wchar_t filenamebuf[MAX_PATH * 2]; * Use VirtualAlloc to allocate pages for the buffer to avoid overflowing the stack.
wchar_t crash_msgW[65536]; * Avoid the heap in case the crash is because the heap became corrupted. */
/* Convert unix -> dos newlines because the edit box only supports that properly :( */ const size_t total_length = crash_desc_buf_length * sizeof(wchar_t) +
const char *unix_nl = CrashLogWindows::current->crashlog.data(); crashlog_length * sizeof(wchar_t) +
char dos_nl[65536]; filename_buf_length * sizeof(wchar_t) * filename_count +
char *p = dos_nl; crashlog_length;
void *raw_buffer = VirtualAlloc(nullptr, total_length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
wchar_t *crash_desc_buf = reinterpret_cast<wchar_t *>(raw_buffer);
wchar_t *crashlog_buf = crash_desc_buf + crash_desc_buf_length;
wchar_t *filename_buf = crashlog_buf + crashlog_length;
char *crashlog_dos_nl = reinterpret_cast<char *>(filename_buf + filename_buf_length * filename_count);
/* Convert unix -> dos newlines because the edit box only supports that properly. */
const char *crashlog_unix_nl = CrashLogWindows::current->crashlog.data();
char *p = crashlog_dos_nl;
char32_t c; char32_t c;
while ((c = Utf8Consume(&unix_nl)) && p < lastof(dos_nl) - 4) { // 4 is max number of bytes per character while ((c = Utf8Consume(&crashlog_unix_nl))) {
if (c == '\n') p += Utf8Encode(p, '\r'); if (c == '\n') p += Utf8Encode(p, '\r');
p += Utf8Encode(p, c); p += Utf8Encode(p, c);
} }
*p = '\0'; *p = '\0';
/* Add path to all files to the crash window text */ _snwprintf(
size_t len = wcslen(_crash_desc) + 2; crash_desc_buf,
len += wcslen(convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf))) + 2; crash_desc_buf_length,
len += wcslen(convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf))) + 2; _crash_desc,
len += wcslen(convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf))) + 1; convert_to_fs(CrashLogWindows::current->crashlog_filename, filename_buf + filename_buf_length * 0, filename_buf_length),
convert_to_fs(CrashLogWindows::current->crashdump_filename, filename_buf + filename_buf_length * 1, filename_buf_length),
convert_to_fs(CrashLogWindows::current->savegame_filename, filename_buf + filename_buf_length * 2, filename_buf_length),
convert_to_fs(CrashLogWindows::current->screenshot_filename, filename_buf + filename_buf_length * 3, filename_buf_length)
);
static wchar_t text[lengthof(_crash_desc) + 3 * MAX_PATH * 2 + 7]; SetDlgItemText(wnd, 10, crash_desc_buf);
int printed = _snwprintf(text, len, _crash_desc, convert_to_fs(CrashLogWindows::current->crashlog_filename, filenamebuf, lengthof(filenamebuf))); SetDlgItemText(wnd, 11, convert_to_fs(crashlog_dos_nl, crashlog_buf, crashlog_length));
if (printed < 0 || (size_t)printed > len) {
MessageBox(wnd, L"Catastrophic failure trying to display crash message. Could not perform text formatting.", L"OpenTTD", MB_ICONERROR);
return FALSE;
}
if (convert_to_fs(CrashLogWindows::current->crashdump_filename, filenamebuf, lengthof(filenamebuf))[0] != L'\0') {
wcscat(text, L"\n");
wcscat(text, filenamebuf);
}
if (convert_to_fs(CrashLogWindows::current->screenshot_filename, filenamebuf, lengthof(filenamebuf))[0] != L'\0') {
wcscat(text, L"\n");
wcscat(text, filenamebuf);
}
SetDlgItemText(wnd, 10, text);
SetDlgItemText(wnd, 11, convert_to_fs(dos_nl, crash_msgW, lengthof(crash_msgW)));
SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE); SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
SetWndSize(wnd, -1); SetWndSize(wnd, -1);
} return TRUE; } return TRUE;

View File

@ -44,16 +44,16 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT
// Dialog // Dialog
// //
100 DIALOG DISCARDABLE 0, 0, 305, 101 100 DIALOG DISCARDABLE 0, 0, 305, 109
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Fatal Application Failure" CAPTION "Fatal Application Failure"
FONT 8, "MS Sans Serif" FONT 8, "MS Sans Serif"
BEGIN BEGIN
PUSHBUTTON "&Close",12,7,82,60,14 PUSHBUTTON "&Close",12,7,90,60,14
PUSHBUTTON "",15,238,82,60,14 PUSHBUTTON "",15,238,90,60,14
EDITTEXT 11,7,103,291,118,ES_MULTILINE | ES_READONLY | WS_VSCROLL | EDITTEXT 11,7,111,291,118,ES_MULTILINE | ES_READONLY | WS_VSCROLL |
WS_HSCROLL | NOT WS_TABSTOP WS_HSCROLL | NOT WS_TABSTOP
LTEXT "",10,36,5,262,72 LTEXT "",10,36,5,262,80
ICON 100,IDC_STATIC,9,9,20,20 ICON 100,IDC_STATIC,9,9,20,20
END END