Skip to content

Commit 686aeed

Browse files
committed
debug.zig: prevent infinite loops during backtraces
1 parent 2e27184 commit 686aeed

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 number of frames 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
}
@@ -875,8 +886,14 @@ pub const StackIterator = struct {
875886
var address = it.next_internal() orelse return null;
876887

877888
if (it.first_address) |first_address| {
889+
var depth: usize = 0;
878890
while (address != first_address) {
879891
address = it.next_internal() orelse return null;
892+
893+
depth += 1;
894+
if (depth > max_stack_trace_depth) {
895+
return null;
896+
}
880897
}
881898
it.first_address = null;
882899
}
@@ -985,6 +1002,8 @@ pub fn writeCurrentStackTrace(
9851002
} else null) orelse StackIterator.init(start_addr, null);
9861003
defer it.deinit();
9871004

1005+
var depth: usize = 0;
1006+
9881007
while (it.next()) |return_address| {
9891008
printLastUnwindError(&it, debug_info, out_stream, tty_config);
9901009

@@ -995,6 +1014,12 @@ pub fn writeCurrentStackTrace(
9951014
// same behaviour for x86-windows-msvc
9961015
const address = return_address -| 1;
9971016
try printSourceAtAddress(debug_info, out_stream, address, tty_config);
1017+
1018+
depth += 1;
1019+
if (depth > max_stack_trace_depth) {
1020+
out_stream.print("Abandoned stack trace after {} frames.\n", .{max_stack_trace_depth}) catch {};
1021+
break;
1022+
}
9981023
} else printLastUnwindError(&it, debug_info, out_stream, tty_config);
9991024
}
10001025

0 commit comments

Comments
 (0)