Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions SPECS/binutils/CVE-2025-69645.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
From cdb728d4da6184631989b192f1022c219dea7677 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
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.

Upstream Patch Reference: https://sourceware.org/git/?p=binutils-gdb.git;a=patch;h=cdb728d4da6184631989b192f1022c219dea7677
---
binutils/dwarf.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index ea83e35a..25013132 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -3707,8 +3707,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_types);
-
if (compunit.cu_version < 5)
{
compunit.cu_unit_type = DW_UT_compile;
@@ -3718,8 +3716,6 @@ process_debug_info (struct dwarf_section * section,
else
{
SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
- do_types = (compunit.cu_unit_type == DW_UT_type);
-
SAFE_BYTE_GET_AND_INC (compunit.cu_pointer_size, hdrptr, 1, end_cu);
}

@@ -3733,6 +3729,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_types);
if (this_set == NULL)
{
abbrev_base = 0;
@@ -3789,8 +3786,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_types);
-
if (compunit.cu_version < 5)
{
compunit.cu_unit_type = DW_UT_compile;
@@ -3800,13 +3795,12 @@ process_debug_info (struct dwarf_section * section,
else
{
SAFE_BYTE_GET_AND_INC (compunit.cu_unit_type, hdrptr, 1, end_cu);
- do_types = (compunit.cu_unit_type == DW_UT_type);
-
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_types);
if (this_set == NULL)
{
abbrev_base = 0;
@@ -3838,7 +3832,7 @@ process_debug_info (struct dwarf_section * section,
compunit.cu_pointer_size = offset_size;
}

- if (do_types)
+ if (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);
@@ -3853,7 +3847,7 @@ process_debug_info (struct dwarf_section * section,
if ((do_loc || do_debug_loc || do_debug_ranges || do_debug_info)
&& num_debug_info_entries == 0
&& alloc_num_debug_info_entries > unit
- && ! do_types)
+ && !do_types)
{
free_debug_information (&debug_information[unit]);
memset (&debug_information[unit], 0, sizeof (*debug_information));
@@ -3884,7 +3878,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_types)
+ if (do_types || compunit.cu_unit_type == DW_UT_type)
{
printf (_(" Signature: %#" PRIx64 "\n"), signature);
printf (_(" Type Offset: %#" PRIx64 "\n"), type_offset);
@@ -4121,7 +4115,7 @@ process_debug_info (struct dwarf_section * section,
we need to process .debug_loc and .debug_ranges sections. */
if ((do_loc || do_debug_loc || do_debug_ranges || do_debug_info)
&& num_debug_info_entries == 0
- && ! do_types)
+ && !do_types)
{
if (num_units > alloc_num_debug_info_entries)
num_debug_info_entries = alloc_num_debug_info_entries;
--
2.45.4

Loading
Loading