diff --git a/SOURCES/_gdb.spec.Patch.include b/SOURCES/_gdb.spec.Patch.include index 79b8647..a1230be 100644 --- a/SOURCES/_gdb.spec.Patch.include +++ b/SOURCES/_gdb.spec.Patch.include @@ -479,19 +479,36 @@ Patch115: gdb-rhbz-2130624-assert_in_jit_event_handler.patch # (Luís Ferreira, RHBZ2132600) Patch116: libiberty-rhbz-2132600-prevent-buffer-overflow.patch +# Backport: Fix crash in Fortran code +# (Tom Tromey, RHEL-7328) +Patch117: gdb-rhel-7328-fix-fortran-28801.patch + +# Backport "libiberty: Fix infinite recursion in rust demangler." +# (Nick Clifton) +Patch118: libiberty-infinite-recursion-fix-1-of-3.patch + +# Backport Add a recursion limit to the demangle_const function in the Rust demangler. +# (Nick Clifton, RHEL-4234) +Patch119: libiberty-infinite-recursion-fix-2-of-3.patch + +# Backport Fix typo in recent code to add stack recursion limit to the Rust demangler. +# (Nick Clifton) +Patch120: libiberty-infinite-recursion-fix-3-of-3.patch + # Backport "gdbsupport: make gdb_abspath return an std::string" # (Simon Marchi) -Patch117: gdb-find_and_open_source-empty-string-ub-1of4.patch +Patch121: gdb-find_and_open_source-empty-string-ub-1of4.patch # Backport "gdbsupport: add path_join function" # (Simon Marchi) -Patch118: gdb-find_and_open_source-empty-string-ub-2of4.patch +Patch122: gdb-find_and_open_source-empty-string-ub-2of4.patch # Backport "Fix undefined behaviour dereferencing empty string" -# (Magne Hov, RHEL-18940) -Patch119: gdb-find_and_open_source-empty-string-ub-3of4.patch +# (Magne Hov, RHEL-17631) +Patch123: gdb-find_and_open_source-empty-string-ub-3of4.patch # Backport "gdbsupport: change path_join parameter to # array_view" # (Simon Marchi) -Patch120: gdb-find_and_open_source-empty-string-ub-4of4.patch +Patch124: gdb-find_and_open_source-empty-string-ub-4of4.patch + diff --git a/SOURCES/_gdb.spec.patch.include b/SOURCES/_gdb.spec.patch.include index 4e43cac..97f12c4 100644 --- a/SOURCES/_gdb.spec.patch.include +++ b/SOURCES/_gdb.spec.patch.include @@ -117,4 +117,8 @@ %patch117 -p1 %patch118 -p1 %patch119 -p1 -%patch120 -p1 \ No newline at end of file +%patch120 -p1 +%patch121 -p1 +%patch122 -p1 +%patch123 -p1 +%patch124 -p1 diff --git a/SOURCES/gdb-find_and_open_source-empty-string-ub-3of4.patch b/SOURCES/gdb-find_and_open_source-empty-string-ub-3of4.patch index 7652c4d..4cf6d67 100644 --- a/SOURCES/gdb-find_and_open_source-empty-string-ub-3of4.patch +++ b/SOURCES/gdb-find_and_open_source-empty-string-ub-3of4.patch @@ -4,7 +4,7 @@ Date: Tue, 5 Dec 2023 08:47:16 -0800 Subject: gdb-find_and_open_source-empty-string-ub-3of4.patch ;; Backport "Fix undefined behaviour dereferencing empty string" -;; (Magne Hov, RHEL-18940) +;; (Magne Hov, RHEL-17631) When a source file's dirname is solely made up of directory separators we end up trying to dereference the last character of an empty string diff --git a/SOURCES/gdb-rhel-7328-fix-fortran-28801.patch b/SOURCES/gdb-rhel-7328-fix-fortran-28801.patch new file mode 100644 index 0000000..d724494 --- /dev/null +++ b/SOURCES/gdb-rhel-7328-fix-fortran-28801.patch @@ -0,0 +1,259 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Tom Tromey +Date: Thu, 24 Feb 2022 09:01:42 -0700 +Subject: gdb-rhel-7328-fix-fortran-28801.patch + +;; Backport: Fix crash in Fortran code +;; (Tom Tromey, RHEL-7328) + +PR fortran/28801 points out a gdb crash that can be provoked by +certain Fortran code. The bug is that f77_get_upperbound assumes the +property is either a constant or undefined, but in this case it is +PROP_LOCEXPR. + +This patch fixes the crash by making this function (and the +lower-bound one as well) do the correct check before calling +'const_val'. + +Thanks to Andrew for writing the test case. + +Co-authored-by: Andrew Burgess +Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28801 + +diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c +--- a/gdb/f-valprint.c ++++ b/gdb/f-valprint.c +@@ -47,7 +47,7 @@ int f77_array_offset_tbl[MAX_FORTRAN_DIMS + 1][2]; + LONGEST + f77_get_lowerbound (struct type *type) + { +- if (type->bounds ()->low.kind () == PROP_UNDEFINED) ++ if (type->bounds ()->low.kind () != PROP_CONST) + error (_("Lower bound may not be '*' in F77")); + + return type->bounds ()->low.const_val (); +@@ -56,7 +56,7 @@ f77_get_lowerbound (struct type *type) + LONGEST + f77_get_upperbound (struct type *type) + { +- if (type->bounds ()->high.kind () == PROP_UNDEFINED) ++ if (type->bounds ()->high.kind () != PROP_CONST) + { + /* We have an assumed size array on our hands. Assume that + upper_bound == lower_bound so that we show at least 1 element. +diff --git a/gdb/testsuite/gdb.dwarf2/fortran-var-string.c b/gdb/testsuite/gdb.dwarf2/fortran-var-string.c +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/fortran-var-string.c +@@ -0,0 +1,31 @@ ++/* Copyright 2022 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++/* In the generated DWARF, we'll pretend that ARG is a string with dynamic ++ length. */ ++int ++main_helper (void *arg) ++{ ++ asm ("main_helper_label: .globl main_helper_label"); ++ return 0; ++} ++ ++int ++main (void) ++{ ++ asm ("main_label: .globl main_label"); ++ main_helper (0); ++ return 0; ++} +diff --git a/gdb/testsuite/gdb.dwarf2/fortran-var-string.exp b/gdb/testsuite/gdb.dwarf2/fortran-var-string.exp +new file mode 100644 +--- /dev/null ++++ b/gdb/testsuite/gdb.dwarf2/fortran-var-string.exp +@@ -0,0 +1,175 @@ ++# Copyright 2022 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++load_lib dwarf.exp ++ ++# This test can only be run on targets which support DWARF-2 and use gas. ++if {![dwarf2_support]} { ++ return 0 ++} ++ ++standard_testfile .c -dw.S ++ ++# We need to know the size of integer and address types in order ++# to write some of the debugging info we'd like to generate. ++# ++# For that, we ask GDB by debugging our dynarr-ptr.c program. ++# Any program would do, but since we already have dynarr-ptr.c ++# specifically for this testcase, might as well use that. ++ ++if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { ++ return -1 ++} ++ ++# Make some DWARF for the test. ++set asm_file [standard_output_file $srcfile2] ++Dwarf::assemble $asm_file { ++ set int_size [get_sizeof "int" 4] ++ ++ get_func_info main ++ get_func_info main_helper ++ ++ cu {} { ++ DW_TAG_compile_unit { ++ {DW_AT_language @DW_LANG_Fortran90} ++ {DW_AT_name fortran-var-string.f90} ++ {DW_AT_comp_dir /tmp} ++ } { ++ declare_labels integer_label string_label array_lb_label \ ++ array_ub_label ++ ++ DW_TAG_subprogram { ++ {name main} ++ {low_pc $main_helper_start addr} ++ {high_pc $main_helper_len data8} ++ {DW_AT_type :$integer_label} ++ {DW_AT_decl_file 1 data1} ++ {DW_AT_decl_line 1 data1} ++ } ++ ++ DW_TAG_subprogram { ++ {name test_1_func} ++ {low_pc $main_start addr} ++ {high_pc $main_len data8} ++ {DW_AT_type :$integer_label} ++ {DW_AT_decl_file 1 data1} ++ {DW_AT_decl_line 2 data1} ++ } { ++ formal_parameter { ++ {name arg1} ++ {type :$string_label} ++ } ++ } ++ ++ DW_TAG_subprogram { ++ {name test_2_func} ++ {low_pc $main_start addr} ++ {high_pc $main_len data8} ++ {DW_AT_type :$integer_label} ++ {DW_AT_decl_file 1 data1} ++ {DW_AT_decl_line 3 data1} ++ } { ++ formal_parameter { ++ {name arg1} ++ {type :$array_ub_label} ++ } ++ } ++ ++ DW_TAG_subprogram { ++ {name test_3_func} ++ {low_pc $main_start addr} ++ {high_pc $main_len data8} ++ {DW_AT_type :$integer_label} ++ {DW_AT_decl_file 1 data1} ++ {DW_AT_decl_line 4 data1} ++ } { ++ formal_parameter { ++ {name arg1} ++ {type :$array_lb_label} ++ } ++ } ++ ++ integer_label: DW_TAG_base_type { ++ {DW_AT_byte_size $int_size DW_FORM_sdata} ++ {DW_AT_encoding @DW_ATE_signed} ++ {DW_AT_name integer} ++ } ++ ++ string_label: DW_TAG_string_type { ++ {DW_AT_byte_size $int_size DW_FORM_sdata} ++ {DW_AT_name .str.arg} ++ {DW_AT_string_length {} DW_FORM_block1} ++ } ++ ++ array_lb_label: DW_TAG_array_type { ++ {DW_AT_ordering 1 data1} ++ {DW_AT_type :$integer_label} ++ } { ++ DW_TAG_subrange_type { ++ {DW_AT_lower_bound {} DW_FORM_block1} ++ {DW_AT_upper_bound 10 DW_FORM_data1} ++ } ++ } ++ ++ array_ub_label: DW_TAG_array_type { ++ {DW_AT_ordering 1 data1} ++ {DW_AT_type :$integer_label} ++ } { ++ DW_TAG_subrange_type { ++ {DW_AT_upper_bound {} DW_FORM_block1} ++ } ++ } ++ } ++ } ++} ++ ++# Now that we've generated the DWARF debugging info, rebuild our ++# program using our debug info instead of the info generated by ++# the compiler. ++ ++if { [prepare_for_testing "failed to prepare" ${testfile} \ ++ [list $srcfile $asm_file] {nodebug}] } { ++ return -1 ++} ++ ++if ![runto_main] { ++ return -1 ++} ++ ++gdb_test_no_output "set language fortran" ++ ++gdb_test "info functions test_1_func" \ ++ "2:\\s+integer test_1_func\\(character\\*\\(\\*\\)\\);" ++ ++# We print `1` here as the bound because GDB treats this as an assumed ++# size array, and just reports the lower bound value for the upper ++# bound. ++# ++# We might, in the future, decide that there's a better way we could ++# tell the user about the type of this array argument, when that ++# happens it's OK to change the expected results here. ++gdb_test "info functions test_2_func" \ ++ "3:\\s+integer test_2_func\\(integer \\(1\\)\\);" ++ ++# It's not completely clear that this error is correct here. Why ++# can't the lower bound be a dynamic expression? ++# ++# This test was initially added to guard against the case where GDB ++# was crashing if/when it saw this situation. ++# ++# If later on, GDB's handling of array types with a dynamic loewr ++# bound changes, then it is possible that the expected result here ++# should change. ++gdb_test "info functions test_3_func" \ ++ "4:\\s+Lower bound may not be '\\*' in F77" diff --git a/SOURCES/libiberty-infinite-recursion-fix-1-of-3.patch b/SOURCES/libiberty-infinite-recursion-fix-1-of-3.patch new file mode 100644 index 0000000..0800f98 --- /dev/null +++ b/SOURCES/libiberty-infinite-recursion-fix-1-of-3.patch @@ -0,0 +1,119 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Mon, 31 Jan 2022 14:28:42 +0000 +Subject: libiberty-infinite-recursion-fix-1-of-3.patch + +;; Backport "libiberty: Fix infinite recursion in rust demangler." +;; (Nick Clifton) + +libiberty/ + PR demangler/98886 + PR demangler/99935 + * rust-demangle.c (struct rust_demangler): Add a recursion + counter. + (demangle_path): Increment/decrement the recursion counter upon + entry and exit. Fail if the counter exceeds a fixed limit. + (demangle_type): Likewise. + (rust_demangle_callback): Initialise the recursion counter, + disabling if requested by the option flags. + +diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c +--- a/libiberty/rust-demangle.c ++++ b/libiberty/rust-demangle.c +@@ -74,6 +74,12 @@ struct rust_demangler + /* Rust mangling version, with legacy mangling being -1. */ + int version; + ++ /* Recursion depth. */ ++ unsigned int recursion; ++ /* Maximum number of times demangle_path may be called recursively. */ ++#define RUST_MAX_RECURSION_COUNT 1024 ++#define RUST_NO_RECURSION_LIMIT ((unsigned int) -1) ++ + uint64_t bound_lifetime_depth; + }; + +@@ -671,6 +677,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) + if (rdm->errored) + return; + ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ { ++ ++ rdm->recursion; ++ if (rdm->recursion > RUST_MAX_RECURSION_COUNT) ++ /* FIXME: There ought to be a way to report ++ that the recursion limit has been reached. */ ++ goto fail_return; ++ } ++ + switch (tag = next (rdm)) + { + case 'C': +@@ -688,10 +703,7 @@ demangle_path (struct rust_demangler *rdm, int in_value) + case 'N': + ns = next (rdm); + if (!ISLOWER (ns) && !ISUPPER (ns)) +- { +- rdm->errored = 1; +- return; +- } ++ goto fail_return; + + demangle_path (rdm, in_value); + +@@ -776,9 +788,15 @@ demangle_path (struct rust_demangler *rdm, int in_value) + } + break; + default: +- rdm->errored = 1; +- return; ++ goto fail_return; + } ++ goto pass_return; ++ ++ fail_return: ++ rdm->errored = 1; ++ pass_return: ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ -- rdm->recursion; + } + + static void +@@ -870,6 +888,19 @@ demangle_type (struct rust_demangler *rdm) + return; + } + ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ { ++ ++ rdm->recursion; ++ if (rdm->recursion > RUST_MAX_RECURSION_COUNT) ++ /* FIXME: There ought to be a way to report ++ that the recursion limit has been reached. */ ++ { ++ rdm->errored = 1; ++ -- rdm->recursion; ++ return; ++ } ++ } ++ + switch (tag) + { + case 'R': +@@ -1030,6 +1061,9 @@ demangle_type (struct rust_demangler *rdm) + rdm->next--; + demangle_path (rdm, 0); + } ++ ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ -- rdm->recursion; + } + + /* A trait in a trait object may have some "existential projections" +@@ -1317,6 +1351,7 @@ rust_demangle_callback (const char *mangled, int options, + rdm.skipping_printing = 0; + rdm.verbose = (options & DMGL_VERBOSE) != 0; + rdm.version = 0; ++ rdm.recursion = (options & DMGL_NO_RECURSE_LIMIT) ? RUST_NO_RECURSION_LIMIT : 0; + rdm.bound_lifetime_depth = 0; + + /* Rust symbols always start with _R (v0) or _ZN (legacy). */ diff --git a/SOURCES/libiberty-infinite-recursion-fix-2-of-3.patch b/SOURCES/libiberty-infinite-recursion-fix-2-of-3.patch new file mode 100644 index 0000000..e7dc83d --- /dev/null +++ b/SOURCES/libiberty-infinite-recursion-fix-2-of-3.patch @@ -0,0 +1,85 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Fri, 1 Jul 2022 15:58:52 +0100 +Subject: libiberty-infinite-recursion-fix-2-of-3.patch + +;; Backport Add a recursion limit to the demangle_const function in the Rust demangler. +;; (Nick Clifton, RHEL-4234) + +libiberty/ + PR demangler/105039 + * rust-demangle.c (demangle_const): Add recursion limit. + +diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c +--- a/libiberty/rust-demangle.c ++++ b/libiberty/rust-demangle.c +@@ -126,7 +126,7 @@ parse_integer_62 (struct rust_demangler *rdm) + return 0; + + x = 0; +- while (!eat (rdm, '_')) ++ while (!eat (rdm, '_') && !rdm->errored) + { + c = next (rdm); + x *= 62; +@@ -1148,6 +1148,15 @@ demangle_const (struct rust_demangler *rdm) + if (rdm->errored) + return; + ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ { ++ ++ rdm->recursion; ++ if (rdm->recursion > RUST_MAX_RECURSION_COUNT) ++ /* FIXME: There ought to be a way to report ++ that the recursion limit has been reached. */ ++ goto fail_return; ++ } ++ + if (eat (rdm, 'B')) + { + backref = parse_integer_62 (rdm); +@@ -1158,7 +1167,7 @@ demangle_const (struct rust_demangler *rdm) + demangle_const (rdm); + rdm->next = old_next; + } +- return; ++ goto pass_return; + } + + ty_tag = next (rdm); +@@ -1167,7 +1176,7 @@ demangle_const (struct rust_demangler *rdm) + /* Placeholder. */ + case 'p': + PRINT ("_"); +- return; ++ goto pass_return; + + /* Unsigned integer types. */ + case 'h': +@@ -1200,18 +1209,20 @@ demangle_const (struct rust_demangler *rdm) + break; + + default: +- rdm->errored = 1; +- return; ++ goto fail_return; + } + +- if (rdm->errored) +- return; +- +- if (rdm->verbose) ++ if (!rdm->errored && rdm->verbose) + { + PRINT (": "); + PRINT (basic_type (ty_tag)); + } ++ ++ fail_return: ++ rdm->errored = 1; ++ pass_return: ++ if (rdm->recursion != RUST_NO_RECURSION_LIMIT) ++ -- rdm->recursion; + } + + static void diff --git a/SOURCES/libiberty-infinite-recursion-fix-3-of-3.patch b/SOURCES/libiberty-infinite-recursion-fix-3-of-3.patch new file mode 100644 index 0000000..73d9c49 --- /dev/null +++ b/SOURCES/libiberty-infinite-recursion-fix-3-of-3.patch @@ -0,0 +1,23 @@ +From FEDORA_PATCHES Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Mon, 4 Jul 2022 16:31:18 +0100 +Subject: libiberty-infinite-recursion-fix-3-of-3.patch + +;; Backport Fix typo in recent code to add stack recursion limit to the Rust demangler. +;; (Nick Clifton) + +libiberty + * rust-demangle.c (demangle_const): Add a missing goto pass_return + at the end of the function. + +diff --git a/libiberty/rust-demangle.c b/libiberty/rust-demangle.c +--- a/libiberty/rust-demangle.c ++++ b/libiberty/rust-demangle.c +@@ -1217,6 +1217,7 @@ demangle_const (struct rust_demangler *rdm) + PRINT (": "); + PRINT (basic_type (ty_tag)); + } ++ goto pass_return; + + fail_return: + rdm->errored = 1; diff --git a/SPECS/gdb.spec b/SPECS/gdb.spec index 0d51f1b..f307aa6 100644 --- a/SPECS/gdb.spec +++ b/SPECS/gdb.spec @@ -37,7 +37,7 @@ Version: 10.2 # The release always contains a leading reserved number, start it at 1. # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing. -Release: 11.1%{?dist} +Release: 13%{?dist} License: GPLv3+ and GPLv3+ with exceptions and GPLv2+ and GPLv2+ with exceptions and GPL+ and LGPLv2+ and LGPLv3+ and BSD and Public Domain and GFDL # Do not provide URL for snapshots as the file lasts there only for 2 days. @@ -1158,9 +1158,21 @@ fi %endif %changelog -* Mon Jan 8 2024 Keith Seitz - 10.2-11.1.el9 +* Wed Dec 13 2023 Keith Seitz - 10.2-13.el9 - Backport patches for "Fix undefined behaviour dereferencing empty string" - (Magne Hov et al, RHEL-18940) + (Magne Hov et al, RHEL-17631) + +* Tue Oct 3 2023 Guinevere Larsen - 10.2-12.el9 +- Backport "libiberty: Fix infinite recursion in rust demangler." + (Nick Clifton) +- Backport Add a recursion limit to the demangle_const function in the Rust demangler. + (Nick Clifton, RHEL-4234) +- Backport Fix typo in recent code to add stack recursion limit to the Rust demangler. + (Nick Clifton) + +* Tue Oct 3 2023 Guinevere Larsen +- Backport "Fix crash in Fortran code" + (Tom Tromey, RHEL-7328) * Wed Mar 29 2023 Bruno Larsen - 10.2-11.el9 - Backport "libiberty: prevent buffer overflow when decoding user input"