mirror of
https://github.com/SWG-Source/src.git
synced 2026-07-31 00:15:55 -04:00
Stop dereferencing a 32-bit frame offset in the SIGSEGV handler
JavaLibrary::fatalHandler() read the faulting address from a hardcoded 0x44 byte offset into its own frame. That constant describes the 32-bit x86 frame layout; on x86-64 it is misaligned and points at unrelated stack memory, and dereferencing it from inside a SIGSEGV handler risks a recursive fault that loses the crash report entirely. The original code carried a TODO noting the offset was never verified. Restrict that probe to __i386__ and rely on the portable __builtin_return_address() probe already present below it. Zero initialise the lib and file buffers, which the strstr() checks read whenever a lookup fails.
This commit is contained in:
@@ -781,16 +781,26 @@ void JavaLibrary::fatalHandler(int signum)
|
||||
{
|
||||
// try to see if our call stack came from C or Java
|
||||
void *frameAddress = __builtin_frame_address(0);
|
||||
// the address that generated the segfault is stored at an offset of 0x44 from
|
||||
// the frame address
|
||||
// @todo: find documentation on the offset to verify it is stable
|
||||
void *crashAddress1 = *((void**)((static_cast<char *>(frameAddress)) + 0x44));
|
||||
|
||||
// pass the crash address to addr2line to get the file name where the crash occurred
|
||||
// These are zero initialized because the strstr() checks below read them
|
||||
// whenever a lookup fails.
|
||||
static const int BUFLEN = 2048;
|
||||
char lib1[BUFLEN], lib2[BUFLEN];
|
||||
char file1[BUFLEN], file2[BUFLEN];
|
||||
int line1, line2;
|
||||
bool result1 = DebugHelp::lookupAddress(reinterpret_cast<uint64>(crashAddress1), lib1, file1, BUFLEN, line1);
|
||||
char lib1[BUFLEN] = { '\0' }, lib2[BUFLEN] = { '\0' };
|
||||
char file1[BUFLEN] = { '\0' }, file2[BUFLEN] = { '\0' };
|
||||
int line1 = 0, line2 = 0;
|
||||
bool result1 = false;
|
||||
|
||||
// The faulting address used to be read from a fixed 0x44 byte offset into
|
||||
// this frame. That constant describes the 32-bit x86 frame layout only; on
|
||||
// x86-64 it is both misaligned and meaningless, and dereferencing it from
|
||||
// inside a SIGSEGV handler risks a recursive fault that loses the crash
|
||||
// report entirely. The __builtin_return_address() probe below is portable
|
||||
// and already covers this case.
|
||||
#if defined(__i386__)
|
||||
void *crashAddress1 = *((void**)((static_cast<char *>(frameAddress)) + 0x44));
|
||||
result1 = DebugHelp::lookupAddress(reinterpret_cast<uint64>(crashAddress1), lib1, file1, BUFLEN, line1);
|
||||
#endif
|
||||
|
||||
// do a second test based on the return address
|
||||
// it turns out that in some java crashes we don't even have 2 return
|
||||
|
||||
Reference in New Issue
Block a user