mirror of https://github.com/OpenTTD/OpenTTD
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.pull/11243/head
parent
de5e338a76
commit
b0d7cfaa3d
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue