From 12275cf4b9a1e02e08aef8e1b29e5accb16268f1 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Wed, 28 Aug 2024 05:58:10 -0400 Subject: Dwarf: fix parsing self-hosted debug info for stack traces --- lib/std/debug/Dwarf.zig | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'lib/std/debug/Dwarf.zig') diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 7cce30df38..21d60214dd 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -279,10 +279,11 @@ pub const Die = struct { }; } - fn getAttrRef(self: *const Die, id: u64) !u64 { + fn getAttrRef(self: *const Die, id: u64, unit_offset: u64, unit_len: u64) !u64 { const form_value = self.getAttr(id) orelse return error.MissingDebugInfo; return switch (form_value.*) { - .ref => |value| value, + .ref => |offset| if (offset < unit_len) unit_offset + offset else bad(), + .ref_addr => |addr| addr, else => bad(), }; } @@ -428,14 +429,14 @@ pub const ExceptionFrameHeader = struct { }; const fde_entry_header = try EntryHeader.read(&eh_frame_fbr, if (eh_frame_len == null) ma else null, .eh_frame); - if (!self.isValidPtr(u8, @intFromPtr(&fde_entry_header.entry_bytes[fde_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad(); + if (fde_entry_header.entry_bytes.len > 0 and !self.isValidPtr(u8, @intFromPtr(&fde_entry_header.entry_bytes[fde_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad(); if (fde_entry_header.type != .fde) return bad(); // CIEs always come before FDEs (the offset is a subtraction), so we can assume this memory is readable const cie_offset = fde_entry_header.type.fde; try eh_frame_fbr.seekTo(cie_offset); const cie_entry_header = try EntryHeader.read(&eh_frame_fbr, if (eh_frame_len == null) ma else null, .eh_frame); - if (!self.isValidPtr(u8, @intFromPtr(&cie_entry_header.entry_bytes[cie_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad(); + if (cie_entry_header.entry_bytes.len > 0 and !self.isValidPtr(u8, @intFromPtr(&cie_entry_header.entry_bytes[cie_entry_header.entry_bytes.len - 1]), ma, eh_frame_len)) return bad(); if (cie_entry_header.type != .cie) return bad(); cie.* = try CommonInformationEntry.parse( @@ -942,13 +943,12 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void { defer fbr.pos = after_die_offset; // Follow the DIE it points to and repeat - const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin); - if (ref_offset > next_offset) return bad(); - try fbr.seekTo(this_unit_offset + ref_offset); + const ref_offset = try this_die_obj.getAttrRef(AT.abstract_origin, this_unit_offset, next_offset); + try fbr.seekTo(ref_offset); this_die_obj = (try parseDie( &fbr, attrs_bufs[2], - abbrev_table, + abbrev_table, // wrong abbrev table for different cu unit_header.format, )) orelse return bad(); } else if (this_die_obj.getAttr(AT.specification)) |_| { @@ -956,13 +956,12 @@ fn scanAllFunctions(di: *Dwarf, allocator: Allocator) ScanError!void { defer fbr.pos = after_die_offset; // Follow the DIE it points to and repeat - const ref_offset = try this_die_obj.getAttrRef(AT.specification); - if (ref_offset > next_offset) return bad(); - try fbr.seekTo(this_unit_offset + ref_offset); + const ref_offset = try this_die_obj.getAttrRef(AT.specification, this_unit_offset, next_offset); + try fbr.seekTo(ref_offset); this_die_obj = (try parseDie( &fbr, attrs_bufs[2], - abbrev_table, + abbrev_table, // wrong abbrev table for different cu unit_header.format, )) orelse return bad(); } else { @@ -1494,7 +1493,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) ! } } else { const FileEntFmt = struct { - content_type_code: u8, + content_type_code: u16, form_code: u16, }; { @@ -1539,7 +1538,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, compile_unit: *CompileUnit) ! if (file_name_entry_format_count > file_ent_fmt_buf.len) return bad(); for (file_ent_fmt_buf[0..file_name_entry_format_count]) |*ent_fmt| { ent_fmt.* = .{ - .content_type_code = try fbr.readUleb128(u8), + .content_type_code = try fbr.readUleb128(u16), .form_code = try fbr.readUleb128(u16), }; } -- cgit v1.2.3