diff --git a/CHANGELOG.md b/CHANGELOG.md index d8549116a..285fb50ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ **Fixes**: +- native: Read frame records at pointer width in the crash daemon's frame-pointer walk, so 32-bit targets no longer read two stack slots per pointer. ([#2052](https://github.com/getsentry/sentry-native/pull/2052)) - Prevent backend state races when `sentry_reinstall_backend` runs concurrently with scope observer callbacks. ([#2041](https://github.com/getsentry/sentry-native/pull/2041)) - `sentry_set_trace` omits `parent_span_id` when the caller does not provide one, instead of serializing it as `null`. ([#2047](https://github.com/getsentry/sentry-native/pull/2047)) - Native/Linux i386: write valid thread stack descriptors to minidumps when stack addresses use the upper half of the 32-bit address space. ([#2054](https://github.com/getsentry/sentry-native/pull/2054)) diff --git a/src/backends/native/sentry_crash_daemon.c b/src/backends/native/sentry_crash_daemon.c index 369e3cd1d..980de372b 100644 --- a/src/backends/native/sentry_crash_daemon.c +++ b/src/backends/native/sentry_crash_daemon.c @@ -590,12 +590,19 @@ static bool read_stack_value(const uint8_t *stack_buf, uint64_t stack_start, uint64_t stack_size, uint64_t addr, uint64_t *out_value) { - if (addr < stack_start - || addr + sizeof(uint64_t) > stack_start + stack_size) { + // Range-check by subtraction: `addr` comes from a frame pointer in a + // crashed process, and a corrupted value near the top of the address + // space would wrap an `addr + size` sum past the naive comparison. + if (addr < stack_start) { return false; } uint64_t offset = addr - stack_start; - memcpy(out_value, stack_buf + offset, sizeof(uint64_t)); + if (offset > stack_size || stack_size - offset < sizeof(uintptr_t)) { + return false; + } + uintptr_t value = 0; + memcpy(&value, stack_buf + (size_t)offset, sizeof(value)); + *out_value = (uint64_t)value; return true; } @@ -1112,7 +1119,7 @@ build_stacktrace_for_thread( uint64_t return_addr = 0; // Read saved frame pointer and return address - // Frame layout: [FP+0] = saved FP, [FP+8] = return addr + // Frame layout: [FP] = saved FP, [FP + pointer size] = return addr if (!read_stack_value(stack_buf, stack_start, stack_size, current_fp, &saved_fp)) { SENTRY_TRACEF( @@ -1123,9 +1130,9 @@ build_stacktrace_for_thread( break; } if (!read_stack_value(stack_buf, stack_start, stack_size, - current_fp + sizeof(uint64_t), &return_addr)) { + current_fp + sizeof(uintptr_t), &return_addr)) { SENTRY_TRACEF("Cannot read return addr at 0x%llx", - (unsigned long long)(current_fp + sizeof(uint64_t))); + (unsigned long long)(current_fp + sizeof(uintptr_t))); break; } saved_fp = SENTRY__STRIP_PAC(saved_fp);