mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
std.debug: remove @frameAddress() "UAF"
We can't call `@frameAddress()` and then immediately `return`! That invalidates the frame. This *usually* isn't a problem, because the stack walk `next` call will *probably* have a stack frame and it will *probably* be at the exact same address, but neither of those is a guarantee. On powerpc, presumably some unfortunate inlining was going on, so this frame was indeed invalidated when we started walking frames. We need to explicitly pass `@frameAddress` into any function which will return before we actually walk the stack. Pretty simple patch. Resolves: #24970
This commit is contained in:
parent
151c7dc74b
commit
a31950aa57
2 changed files with 10 additions and 20 deletions
|
|
@ -440,7 +440,7 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext, stderr: *Writer) void {
|
|||
return;
|
||||
}
|
||||
|
||||
var it = StackIterator.initWithContext(null, debug_info, context) catch return;
|
||||
var it = StackIterator.initWithContext(null, debug_info, context, @frameAddress()) catch return;
|
||||
defer it.deinit();
|
||||
|
||||
// DWARF unwinding on aarch64-macos is not complete so we need to get pc address from mcontext
|
||||
|
|
@ -499,12 +499,7 @@ pub fn captureStackTrace(first_address: ?usize, stack_trace: *std.builtin.StackT
|
|||
// TODO: This should use the DWARF unwinder if .eh_frame_hdr is available (so that full debug info parsing isn't required).
|
||||
// A new path for loading SelfInfo needs to be created which will only attempt to parse in-memory sections, because
|
||||
// stopping to load other debug info (ie. source line info) from disk here is not required for unwinding.
|
||||
if (builtin.cpu.arch == .powerpc64) {
|
||||
// https://github.com/ziglang/zig/issues/24970
|
||||
stack_trace.index = 0;
|
||||
return;
|
||||
}
|
||||
var it = StackIterator.init(first_address, null);
|
||||
var it = StackIterator.init(first_address, @frameAddress());
|
||||
defer it.deinit();
|
||||
for (stack_trace.instruction_addresses, 0..) |*addr, i| {
|
||||
addr.* = it.next() orelse {
|
||||
|
|
@ -787,7 +782,7 @@ pub const StackIterator = struct {
|
|||
failed: bool = false,
|
||||
} else void = if (have_ucontext) null else {},
|
||||
|
||||
pub fn init(first_address: ?usize, fp: ?usize) StackIterator {
|
||||
pub fn init(first_address: ?usize, fp: usize) StackIterator {
|
||||
if (native_arch.isSPARC()) {
|
||||
// Flush all the register windows on stack.
|
||||
asm volatile (if (builtin.cpu.has(.sparc, .v9))
|
||||
|
|
@ -799,23 +794,18 @@ pub const StackIterator = struct {
|
|||
|
||||
return .{
|
||||
.first_address = first_address,
|
||||
// TODO: this is a workaround for #16876
|
||||
//.fp = fp orelse @frameAddress(),
|
||||
.fp = fp orelse blk: {
|
||||
const fa = @frameAddress();
|
||||
break :blk fa;
|
||||
},
|
||||
.fp = fp,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn initWithContext(first_address: ?usize, debug_info: *SelfInfo, context: *posix.ucontext_t) !StackIterator {
|
||||
pub fn initWithContext(first_address: ?usize, debug_info: *SelfInfo, context: *posix.ucontext_t, fp: usize) !StackIterator {
|
||||
// The implementation of DWARF unwinding on aarch64-macos is not complete. However, Apple mandates that
|
||||
// the frame pointer register is always used, so on this platform we can safely use the FP-based unwinder.
|
||||
if (builtin.target.os.tag.isDarwin() and native_arch == .aarch64)
|
||||
return init(first_address, @truncate(context.mcontext.ss.fp));
|
||||
|
||||
if (SelfInfo.supports_unwinding) {
|
||||
var iterator = init(first_address, null);
|
||||
var iterator = init(first_address, fp);
|
||||
iterator.unwind_state = .{
|
||||
.debug_info = debug_info,
|
||||
.dwarf_context = try SelfInfo.UnwindContext.init(debug_info.allocator, context),
|
||||
|
|
@ -823,7 +813,7 @@ pub const StackIterator = struct {
|
|||
return iterator;
|
||||
}
|
||||
|
||||
return init(first_address, null);
|
||||
return init(first_address, fp);
|
||||
}
|
||||
|
||||
pub fn deinit(it: *StackIterator) void {
|
||||
|
|
@ -981,8 +971,8 @@ pub fn writeCurrentStackTrace(
|
|||
const has_context = getContext(&context);
|
||||
|
||||
var it = (if (has_context) blk: {
|
||||
break :blk StackIterator.initWithContext(start_addr, debug_info, &context) catch null;
|
||||
} else null) orelse StackIterator.init(start_addr, null);
|
||||
break :blk StackIterator.initWithContext(start_addr, debug_info, &context, @frameAddress()) catch null;
|
||||
} else null) orelse StackIterator.init(start_addr, @frameAddress());
|
||||
defer it.deinit();
|
||||
|
||||
while (it.next()) |return_address| {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ noinline fn frame3(expected: *[4]usize, unwound: *[4]usize) void {
|
|||
testing.expect(debug.getContext(&context)) catch @panic("failed to getContext");
|
||||
|
||||
const debug_info = debug.getSelfDebugInfo() catch @panic("failed to openSelfDebugInfo");
|
||||
var it = debug.StackIterator.initWithContext(expected[0], debug_info, &context) catch @panic("failed to initWithContext");
|
||||
var it = debug.StackIterator.initWithContext(expected[0], debug_info, &context, @frameAddress()) catch @panic("failed to initWithContext");
|
||||
defer it.deinit();
|
||||
|
||||
for (unwound) |*addr| {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue