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:
Sais
2026-07-25 03:52:43 -04:00
parent 4fac50d2e5
commit 750f7d8601
@@ -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