Skip to content

Commit 44f476c

Browse files
committed
debug.zig: prevent infinite loops during backtraces
1 parent c7b5dc4 commit 44f476c

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

lib/std/debug.zig

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const native_arch = builtin.cpu.arch;
1313
const native_os = builtin.os.tag;
1414
const native_endian = native_arch.endian();
1515

16+
/// Maximum distance to walk when iterating through a stack trace.
17+
pub const max_stack_trace_depth = 50;
18+
1619
pub const MemoryAccessor = @import("debug/MemoryAccessor.zig");
1720
pub const FixedBufferReader = @import("debug/FixedBufferReader.zig");
1821
pub const Dwarf = @import("debug/Dwarf.zig");
@@ -458,6 +461,8 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
458461
printSourceAtAddress(debug_info, stderr, pc_addr, tty_config) catch return;
459462
}
460463

464+
var depth: usize = 0;
465+
461466
while (it.next()) |return_address| {
462467
printLastUnwindError(&it, debug_info, stderr, tty_config);
463468

@@ -468,6 +473,12 @@ pub fn dumpStackTraceFromBase(context: *ThreadContext) void {
468473
// same behaviour for x86-windows-msvc
469474
const address = if (return_address == 0) return_address else return_address - 1;
470475
printSourceAtAddress(debug_info, stderr, address, tty_config) catch return;
476+
477+
depth += 1;
478+
if (depth > max_stack_trace_depth) {
479+
stderr.print("Abandoned stack trace after {} frames.\n", .{max_stack_trace_depth}) catch {};
480+
break;
481+
}
471482
} else printLastUnwindError(&it, debug_info, stderr, tty_config);
472483
}
473484
}
@@ -870,8 +881,14 @@ pub const StackIterator = struct {
870881
var address = it.next_internal() orelse return null;
871882

872883
if (it.first_address) |first_address| {
884+
var depth: usize = 0;
873885
while (address != first_address) {
874886
address = it.next_internal() orelse return null;
887+
888+
depth += 1;
889+
if (depth > max_stack_trace_depth) {
890+
return null;
891+
}
875892
}
876893
it.first_address = null;
877894
}
@@ -980,6 +997,8 @@ pub fn writeCurrentStackTrace(
980997
} else null) orelse StackIterator.init(start_addr, null);
981998
defer it.deinit();
982999

1000+
var depth: usize = 0;
1001+
9831002
while (it.next()) |return_address| {
9841003
printLastUnwindError(&it, debug_info, out_stream, tty_config);
9851004

@@ -990,6 +1009,12 @@ pub fn writeCurrentStackTrace(
9901009
// same behaviour for x86-windows-msvc
9911010
const address = return_address -| 1;
9921011
try printSourceAtAddress(debug_info, out_stream, address, tty_config);
1012+
1013+
depth += 1;
1014+
if (depth > max_stack_trace_depth) {
1015+
out_stream.print("Abandoned stack trace after {} frames.\n", .{max_stack_trace_depth}) catch {};
1016+
break;
1017+
}
9931018
} else printLastUnwindError(&it, debug_info, out_stream, tty_config);
9941019
}
9951020

0 commit comments

Comments
 (0)