From cdb728d4da6184631989b192f1022c219dea7677 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Sun, 30 Nov 2025 12:51:54 +1030 Subject: [PATCH] PR 33637, abort in byte_get When DWARF5 support was added to binutils in commit 77145576fadc, the loop over CUs in process_debug_info set do_types when finding a DW_UT_type unit, in order to process the signature and type offset entries. Unfortunately that broke debug_information/debug_info_p handling, which previously was allocated and initialised for each unit in .debug_info. debug_info_p was NULL when processing a DWARF4 .debug_types section. After the 77145576fadc change it was possible for debug_infp_p to be non-NULL but point to zeroed data, in particular a zeroed offset_size. A zero for offset_size led to the byte_get_little_endian abort triggered by the fuzzer testcase. I haven't investigated whether there is any need for a valid offset_size when processing a non-fuzzed DWARF4 .debug_types section. Presumably we'd have found that out in the last 6 years if that was the case. We don't want to change debug_information[] for .debug_types! PR 33637 * dwarf.c (process_debug_info): Don't change DO_TYPES flag bit depending on cu_unit_type. Instead test cu_unit_type along with DO_TYPES to handle signature and type_offset for a type unit. Move find_cu_tu_set_v2 call a little later. --- binutils/dwarf.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/binutils/dwarf.c b/binutils/dwarf.c index e10e33095db..2659f25e179 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -3891,8 +3891,6 @@ process_debug_info (struct dwarf_section * section, SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu); - this_set = find_cu_tu_set_v2 (cu_offset, (do_flags & DO_TYPES)); - if (compunit.cu_version < 5) { compunit.cu_unit_type = DW_UT_compile; @@ -3902,11 +3900,6 @@ process_debug_info (struct dwarf_section * section, else { SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu); - if (compunit.cu_unit_type == DW_UT_type) - do_flags |= DO_TYPES; - else - do_flags &= ~DO_TYPES; - SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu); } @@ -3920,6 +3913,7 @@ process_debug_info (struct dwarf_section * section, SAFE_BYTE_GET_AND_INC (dwo_id, hdrptr, 8, end_cu); } + this_set = find_cu_tu_set_v2 (cu_offset, (do_flags & DO_TYPES)); if (this_set == NULL) { abbrev_base = 0; @@ -3976,8 +3970,6 @@ process_debug_info (struct dwarf_section * section, SAFE_BYTE_GET_AND_INC (compunit.cu_version, hdrptr, 2, end_cu); - this_set = find_cu_tu_set_v2 (cu_offset, (do_flags & DO_TYPES)); - if (compunit.cu_version < 5) { compunit.cu_unit_type = DW_UT_compile; @@ -3987,16 +3979,12 @@ process_debug_info (struct dwarf_section * section, else { SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu); - if (compunit.cu_unit_type == DW_UT_type) - do_flags |= DO_TYPES; - else - do_flags &= ~DO_TYPES; - SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu); } SAFE_BYTE_GET_AND_INC (compunit.cu_abbrev_offset, hdrptr, offset_size, end_cu); + this_set = find_cu_tu_set_v2 (cu_offset, (do_flags & DO_TYPES)); if (this_set == NULL) { abbrev_base = 0; @@ -4028,7 +4016,7 @@ process_debug_info (struct dwarf_section * section, compunit.cu_pointer_size = offset_size; } - if (do_flags & DO_TYPES) + if ((do_flags & DO_TYPES) || compunit.cu_unit_type == DW_UT_type) { SAFE_BYTE_GET_AND_INC (signature, hdrptr, 8, end_cu); SAFE_BYTE_GET_AND_INC (type_offset, hdrptr, offset_size, end_cu); @@ -4044,7 +4032,7 @@ process_debug_info (struct dwarf_section * section, || do_debug_ranges || do_debug_info) && num_debug_info_entries == 0 && alloc_num_debug_info_entries > unit - && ! (do_flags & DO_TYPES)) + && !(do_flags & DO_TYPES)) { free_debug_information (&debug_information[unit]); memset (&debug_information[unit], 0, sizeof (*debug_information)); @@ -4075,7 +4063,7 @@ process_debug_info (struct dwarf_section * section, printf (_(" Abbrev Offset: %#" PRIx64 "\n"), compunit.cu_abbrev_offset); printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size); - if (do_flags & DO_TYPES) + if ((do_flags & DO_TYPES) || compunit.cu_unit_type == DW_UT_type) { printf (_(" Signature: %#" PRIx64 "\n"), signature); printf (_(" Type Offset: %#" PRIx64 "\n"), type_offset); @@ -4350,7 +4338,7 @@ process_debug_info (struct dwarf_section * section, we need to process .debug_loc and .debug_ranges sections. */ if (((do_flags & DO_LOC) || do_debug_loc || do_debug_ranges || do_debug_info) && num_debug_info_entries == 0 - && ! (do_flags & DO_TYPES)) + && !(do_flags & DO_TYPES)) { if (num_units > alloc_num_debug_info_entries) num_debug_info_entries = alloc_num_debug_info_entries; -- 2.47.3