import gdb-10.2-13.el9

i9c-beta changed/i9c-beta/gdb-10.2-13.el9
MSVSphere Packaging Team 8 months ago
parent be4417ed8d
commit 0e457516de

@ -479,3 +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)
Patch121: gdb-find_and_open_source-empty-string-ub-1of4.patch
# Backport "gdbsupport: add path_join function"
# (Simon Marchi)
Patch122: gdb-find_and_open_source-empty-string-ub-2of4.patch
# Backport "Fix undefined behaviour dereferencing empty string"
# (Magne Hov, RHEL-17631)
Patch123: gdb-find_and_open_source-empty-string-ub-3of4.patch
# Backport "gdbsupport: change path_join parameter to
# array_view<const char *>"
# (Simon Marchi)
Patch124: gdb-find_and_open_source-empty-string-ub-4of4.patch

@ -114,3 +114,11 @@
%patch114 -p1
%patch115 -p1
%patch116 -p1
%patch117 -p1
%patch118 -p1
%patch119 -p1
%patch120 -p1
%patch121 -p1
%patch122 -p1
%patch123 -p1
%patch124 -p1

@ -0,0 +1,327 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Keith Seitz <keiths@redhat.com>
Date: Mon, 4 Dec 2023 11:04:22 -0800
Subject: gdb-find_and_open_source-empty-string-ub-1of4.patch
;; Backport "gdbsupport: make gdb_abspath return an std::string"
;; (Simon Marchi)
I'm trying to switch these functions to use std::string instead of char
arrays, as much as possible. Some callers benefit from it (can avoid
doing a copy of the result), while others suffer (have to make one more
copy).
Change-Id: Iced49b8ee2f189744c5072a3b217aab5af17a993
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -295,8 +295,8 @@ compile_file_command (const char *args, int from_tty)
error (_("You must provide a filename for this command."));
args = skip_spaces (args);
- gdb::unique_xmalloc_ptr<char> abspath = gdb_abspath (args);
- std::string buffer = string_printf ("#include \"%s\"\n", abspath.get ());
+ std::string abspath = gdb_abspath (args);
+ std::string buffer = string_printf ("#include \"%s\"\n", abspath.c_str ());
eval_compile_command (NULL, buffer.c_str (), scope, NULL);
}
diff --git a/gdb/completer.c b/gdb/completer.c
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -2036,7 +2036,7 @@ gdb_completion_word_break_characters_throw ()
rl_basic_quote_characters = NULL;
}
- return rl_completer_word_break_characters;
+ return (char *) rl_completer_word_break_characters;
}
char *
diff --git a/gdb/corelow.c b/gdb/corelow.c
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -447,7 +447,7 @@ core_target_open (const char *arg, int from_tty)
gdb::unique_xmalloc_ptr<char> filename (tilde_expand (arg));
if (!IS_ABSOLUTE_PATH (filename.get ()))
- filename = gdb_abspath (filename.get ());
+ filename = make_unique_xstrdup (gdb_abspath (filename.get ()).c_str ());
flags = O_BINARY | O_LARGEFILE;
if (write_files)
diff --git a/gdb/dwarf2/index-cache.c b/gdb/dwarf2/index-cache.c
--- a/gdb/dwarf2/index-cache.c
+++ b/gdb/dwarf2/index-cache.c
@@ -291,7 +291,8 @@ set_index_cache_directory_command (const char *arg, int from_tty,
cmd_list_element *element)
{
/* Make sure the index cache directory is absolute and tilde-expanded. */
- gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (index_cache_directory));
+ gdb::unique_xmalloc_ptr<char> abs
+ = make_unique_xstrdup (gdb_abspath (index_cache_directory).c_str ());
xfree (index_cache_directory);
index_cache_directory = abs.release ();
global_index_cache.set_directory (index_cache_directory);
diff --git a/gdb/main.c b/gdb/main.c
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -135,12 +135,7 @@ set_gdb_data_directory (const char *new_datadir)
"../foo" and "../foo" doesn't exist then we'll record $(pwd)/../foo which
isn't canonical, but that's ok. */
if (!IS_ABSOLUTE_PATH (gdb_datadir.c_str ()))
- {
- gdb::unique_xmalloc_ptr<char> abs_datadir
- = gdb_abspath (gdb_datadir.c_str ());
-
- gdb_datadir = abs_datadir.get ();
- }
+ gdb_datadir = gdb_abspath (gdb_datadir.c_str ());
}
/* Relocate a file or directory. PROGNAME is the name by which gdb
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -341,7 +341,7 @@ objfile::objfile (bfd *abfd, const char *name, objfile_flags flags_)
objfile_alloc_data (this);
- gdb::unique_xmalloc_ptr<char> name_holder;
+ std::string name_holder;
if (name == NULL)
{
gdb_assert (abfd == NULL);
@@ -354,7 +354,7 @@ objfile::objfile (bfd *abfd, const char *name, objfile_flags flags_)
else
{
name_holder = gdb_abspath (name);
- expanded_name = name_holder.get ();
+ expanded_name = name_holder.c_str ();
}
original_name = obstack_strdup (&objfile_obstack, expanded_name);
diff --git a/gdb/source.c b/gdb/source.c
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -512,15 +512,15 @@ add_path (const char *dirname, char **which_path, int parse_separators)
for (const gdb::unique_xmalloc_ptr<char> &name_up : dir_vec)
{
- char *name = name_up.get ();
+ const char *name = name_up.get ();
char *p;
struct stat st;
- gdb::unique_xmalloc_ptr<char> new_name_holder;
+ std::string new_name_holder;
/* Spaces and tabs will have been removed by buildargv().
NAME is the start of the directory.
P is the '\0' following the end. */
- p = name + strlen (name);
+ p = name_up.get () + strlen (name);
while (!(IS_DIR_SEPARATOR (*name) && p <= name + 1) /* "/" */
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
@@ -561,16 +561,18 @@ add_path (const char *dirname, char **which_path, int parse_separators)
}
if (name[0] == '~')
- new_name_holder.reset (tilde_expand (name));
+ new_name_holder
+ = gdb::unique_xmalloc_ptr<char[]> (tilde_expand (name)).get ();
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
else if (IS_ABSOLUTE_PATH (name) && p == name + 2) /* "d:" => "d:." */
- new_name_holder.reset (concat (name, ".", (char *) NULL));
+ new_name_holder = std::string (name) + ".";
#endif
else if (!IS_ABSOLUTE_PATH (name) && name[0] != '$')
new_name_holder = gdb_abspath (name);
else
- new_name_holder.reset (savestring (name, p - name));
- name = new_name_holder.get ();
+ new_name_holder = std::string (name, p - name);
+
+ name = new_name_holder.c_str ();
/* Unless it's a variable, check existence. */
if (name[0] != '$')
@@ -915,7 +917,8 @@ openp (const char *path, openp_flags opts, const char *string,
else if ((opts & OPF_RETURN_REALPATH) != 0)
*filename_opened = gdb_realpath (filename);
else
- *filename_opened = gdb_abspath (filename);
+ *filename_opened
+ = make_unique_xstrdup (gdb_abspath (filename).c_str ());
}
errno = last_errno;
diff --git a/gdb/top.c b/gdb/top.c
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -2065,8 +2065,7 @@ init_history (void)
const char *fname = ".gdb_history";
#endif
- gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (fname));
- history_filename = temp.release ();
+ history_filename = xstrdup (gdb_abspath (fname).c_str ());
}
if (!history_filename_empty ())
@@ -2150,10 +2149,10 @@ set_history_filename (const char *args,
that was read. */
if (!history_filename_empty () && !IS_ABSOLUTE_PATH (history_filename))
{
- gdb::unique_xmalloc_ptr<char> temp (gdb_abspath (history_filename));
+ std::string temp = gdb_abspath (history_filename);
xfree (history_filename);
- history_filename = temp.release ();
+ history_filename = xstrdup (temp.c_str ());
}
}
diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
--- a/gdb/tracefile-tfile.c
+++ b/gdb/tracefile-tfile.c
@@ -471,7 +471,7 @@ tfile_target_open (const char *arg, int from_tty)
gdb::unique_xmalloc_ptr<char> filename (tilde_expand (arg));
if (!IS_ABSOLUTE_PATH (filename.get ()))
- filename = gdb_abspath (filename.get ());
+ filename = make_unique_xstrdup (gdb_abspath (filename.get ()).c_str ());
flags = O_BINARY | O_LARGEFILE;
flags |= O_RDONLY;
diff --git a/gdbserver/server.cc b/gdbserver/server.cc
--- a/gdbserver/server.cc
+++ b/gdbserver/server.cc
@@ -93,31 +93,31 @@ bool non_stop;
static struct {
/* Set the PROGRAM_PATH. Here we adjust the path of the provided
binary if needed. */
- void set (gdb::unique_xmalloc_ptr<char> &&path)
+ void set (const char *path)
{
- m_path = std::move (path);
+ m_path = path;
/* Make sure we're using the absolute path of the inferior when
creating it. */
- if (!contains_dir_separator (m_path.get ()))
+ if (!contains_dir_separator (m_path.c_str ()))
{
int reg_file_errno;
/* Check if the file is in our CWD. If it is, then we prefix
its name with CURRENT_DIRECTORY. Otherwise, we leave the
name as-is because we'll try searching for it in $PATH. */
- if (is_regular_file (m_path.get (), &reg_file_errno))
- m_path = gdb_abspath (m_path.get ());
+ if (is_regular_file (m_path.c_str (), &reg_file_errno))
+ m_path = gdb_abspath (m_path.c_str ());
}
}
/* Return the PROGRAM_PATH. */
- char *get ()
- { return m_path.get (); }
+ const char *get ()
+ { return m_path.empty () ? nullptr : m_path.c_str (); }
private:
/* The program name, adjusted if needed. */
- gdb::unique_xmalloc_ptr<char> m_path;
+ std::string m_path;
} program_path;
static std::vector<char *> program_args;
static std::string wrapper_argv;
@@ -3054,7 +3054,7 @@ handle_v_run (char *own_buf)
}
}
else
- program_path.set (gdb::unique_xmalloc_ptr<char> (new_program_name));
+ program_path.set (new_program_name);
/* Free the old argv and install the new one. */
free_vector_argv (program_args);
@@ -3845,7 +3845,7 @@ captured_main (int argc, char *argv[])
int i, n;
n = argc - (next_arg - argv);
- program_path.set (make_unique_xstrdup (next_arg[0]));
+ program_path.set (next_arg[0]);
for (i = 1; i < n; i++)
program_args.push_back (xstrdup (next_arg[i]));
diff --git a/gdbsupport/pathstuff.cc b/gdbsupport/pathstuff.cc
--- a/gdbsupport/pathstuff.cc
+++ b/gdbsupport/pathstuff.cc
@@ -126,23 +126,23 @@ gdb_realpath_keepfile (const char *filename)
/* See gdbsupport/pathstuff.h. */
-gdb::unique_xmalloc_ptr<char>
+std::string
gdb_abspath (const char *path)
{
gdb_assert (path != NULL && path[0] != '\0');
if (path[0] == '~')
- return gdb_tilde_expand_up (path);
+ return gdb_tilde_expand (path);
if (IS_ABSOLUTE_PATH (path) || current_directory == NULL)
- return make_unique_xstrdup (path);
+ return path;
/* Beware the // my son, the Emacs barfs, the botch that catch... */
- return gdb::unique_xmalloc_ptr<char>
- (concat (current_directory,
- IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
- ? "" : SLASH_STRING,
- path, (char *) NULL));
+ return string_printf
+ ("%s%s%s", current_directory,
+ (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
+ ? "" : SLASH_STRING),
+ path);
}
/* See gdbsupport/pathstuff.h. */
@@ -225,8 +225,8 @@ get_standard_cache_dir ()
if (xdg_cache_home != NULL)
{
/* Make sure the path is absolute and tilde-expanded. */
- gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (xdg_cache_home));
- return string_printf ("%s/gdb", abs.get ());
+ std::string abs = gdb_abspath (xdg_cache_home);
+ return string_printf ("%s/gdb", abs.c_str ());
}
#endif
@@ -234,8 +234,8 @@ get_standard_cache_dir ()
if (home != NULL)
{
/* Make sure the path is absolute and tilde-expanded. */
- gdb::unique_xmalloc_ptr<char> abs (gdb_abspath (home));
- return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.get ());
+ std::string abs = gdb_abspath (home);
+ return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.c_str ());
}
return {};
diff --git a/gdbsupport/pathstuff.h b/gdbsupport/pathstuff.h
--- a/gdbsupport/pathstuff.h
+++ b/gdbsupport/pathstuff.h
@@ -49,7 +49,7 @@ extern gdb::unique_xmalloc_ptr<char>
If CURRENT_DIRECTORY is NULL, this function returns a copy of
PATH. */
-extern gdb::unique_xmalloc_ptr<char> gdb_abspath (const char *path);
+extern std::string gdb_abspath (const char *path);
/* If the path in CHILD is a child of the path in PARENT, return a
pointer to the first component in the CHILD's pathname below the

@ -0,0 +1,475 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Keith Seitz <keiths@redhat.com>
Date: Mon, 4 Dec 2023 11:02:16 -0800
Subject: gdb-find_and_open_source-empty-string-ub-2of4.patch
;; Backport "gdbsupport: add path_join function"
;; (Simon Marchi)
In this review [1], Eli pointed out that we should be careful when
concatenating file names to avoid duplicated slashes. On Windows, a
double slash at the beginning of a file path has a special meaning. So
naively concatenating "/" and "foo/bar" would give "//foo/bar", which
would not give the desired results. We already have a few spots doing:
if (first_path ends with a slash)
path = first_path + second_path
else
path = first_path + slash + second_path
In general, I think it's nice to avoid superfluous slashes in file
paths, since they might end up visible to the user and look a bit
unprofessional.
Introduce the path_join function that can be used to join multiple path
components together (along with unit tests).
I initially wanted to make it possible to join two absolute paths, to
support the use case of prepending a sysroot path to a target file path,
or the prepending the debug-file-directory to a target file path. But
the code in solib_find_1 shows that it is more complex than this anyway
(for example, when the right hand side is a Windows path with a drive
letter). So I don't think we need to support that case in path_join.
That also keeps the implementation simpler.
Change a few spots to use path_join to show how it can be used. I
believe that all the spots I changed are guarded by some checks that
ensure the right hand side operand is not an absolute path.
Regression-tested on Ubuntu 18.04. Built-tested on Windows, and I also
ran the new unit-test there.
[1] https://sourceware.org/pipermail/gdb-patches/2022-April/187559.html
Change-Id: I0df889f7e3f644e045f42ff429277b732eb6c752
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -446,6 +446,7 @@ SELFTESTS_SRCS = \
unittests/observable-selftests.c \
unittests/optional-selftests.c \
unittests/parse-connection-spec-selftests.c \
+ unittests/path-join-selftests.c \
unittests/ptid-selftests.c \
unittests/main-thread-selftests.c \
unittests/mkdir-recursive-selftests.c \
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -19,6 +19,7 @@
#include "defs.h"
#include "buildsym-legacy.h"
#include "bfd.h"
+#include "gdbsupport/pathstuff.h"
#include "gdb_obstack.h"
#include "symtab.h"
#include "symfile.h"
@@ -512,27 +513,22 @@ buildsym_compunit::start_subfile (const char *name)
for (subfile = m_subfiles; subfile; subfile = subfile->next)
{
- char *subfile_name;
+ std::string subfile_name;
/* If NAME is an absolute path, and this subfile is not, then
attempt to create an absolute path to compare. */
if (IS_ABSOLUTE_PATH (name)
&& !IS_ABSOLUTE_PATH (subfile->name)
&& subfile_dirname != NULL)
- subfile_name = concat (subfile_dirname, SLASH_STRING,
- subfile->name, (char *) NULL);
+ subfile_name = path_join (subfile_dirname, subfile->name);
else
subfile_name = subfile->name;
- if (FILENAME_CMP (subfile_name, name) == 0)
+ if (FILENAME_CMP (subfile_name.c_str (), name) == 0)
{
m_current_subfile = subfile;
- if (subfile_name != subfile->name)
- xfree (subfile_name);
return;
}
- if (subfile_name != subfile->name)
- xfree (subfile_name);
}
/* This subfile is not known. Add an entry for it. */
diff --git a/gdb/dwarf2/line-header.c b/gdb/dwarf2/line-header.c
--- a/gdb/dwarf2/line-header.c
+++ b/gdb/dwarf2/line-header.c
@@ -24,6 +24,7 @@
#include "dwarf2/read.h"
#include "complaints.h"
#include "filenames.h"
+#include "gdbsupport/pathstuff.h"
void
line_header::add_include_dir (const char *include_dir)
@@ -73,9 +74,7 @@ line_header::file_file_name (int file) const
{
const char *dir = fe->include_dir (this);
if (dir != NULL)
- return gdb::unique_xmalloc_ptr<char> (concat (dir, SLASH_STRING,
- fe->name,
- (char *) NULL));
+ return make_unique_xstrdup (path_join (dir, fe->name).c_str ());
}
return make_unique_xstrdup (fe->name);
}
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -12782,14 +12782,13 @@ open_dwo_file (dwarf2_per_objfile *per_objfile,
if (comp_dir != NULL)
{
- gdb::unique_xmalloc_ptr<char> path_to_try
- (concat (comp_dir, SLASH_STRING, file_name, (char *) NULL));
+ std::string path_to_try = path_join (comp_dir, file_name);
/* NOTE: If comp_dir is a relative path, this will also try the
search path, which seems useful. */
- gdb_bfd_ref_ptr abfd (try_open_dwop_file (per_objfile, path_to_try.get (),
- 0 /*is_dwp*/,
- 1 /*search_cwd*/));
+ gdb_bfd_ref_ptr abfd (try_open_dwop_file
+ (per_objfile, path_to_try.c_str (), 0 /*is_dwp*/, 1 /*search_cwd*/));
+
if (abfd != NULL)
return abfd;
}
@@ -20537,7 +20536,7 @@ static const char *
psymtab_include_file_name (const struct line_header *lh, const file_entry &fe,
const dwarf2_psymtab *pst,
const char *comp_dir,
- gdb::unique_xmalloc_ptr<char> *name_holder)
+ std::string &name_holder)
{
const char *include_name = fe.name;
const char *include_name_to_compare = include_name;
@@ -20546,7 +20545,7 @@ psymtab_include_file_name (const struct line_header *lh, const file_entry &fe,
const char *dir_name = fe.include_dir (lh);
- gdb::unique_xmalloc_ptr<char> hold_compare;
+ std::string hold_compare;
if (!IS_ABSOLUTE_PATH (include_name)
&& (dir_name != NULL || comp_dir != NULL))
{
@@ -20573,26 +20572,23 @@ psymtab_include_file_name (const struct line_header *lh, const file_entry &fe,
if (dir_name != NULL)
{
- name_holder->reset (concat (dir_name, SLASH_STRING,
- include_name, (char *) NULL));
- include_name = name_holder->get ();
+ name_holder = path_join (dir_name, include_name);
+ include_name = name_holder.c_str ();
include_name_to_compare = include_name;
}
if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL)
{
- hold_compare.reset (concat (comp_dir, SLASH_STRING,
- include_name, (char *) NULL));
- include_name_to_compare = hold_compare.get ();
+ hold_compare = path_join (comp_dir, include_name);
+ include_name_to_compare = hold_compare.c_str ();
}
}
pst_filename = pst->filename;
- gdb::unique_xmalloc_ptr<char> copied_name;
+ std::string copied_name;
if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL)
{
- copied_name.reset (concat (pst->dirname, SLASH_STRING,
- pst_filename, (char *) NULL));
- pst_filename = copied_name.get ();
+ copied_name = path_join (pst->dirname, pst_filename);
+ pst_filename = copied_name.c_str ();
}
file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0;
@@ -21303,10 +21299,10 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
for (auto &file_entry : lh->file_names ())
if (file_entry.included_p == 1)
{
- gdb::unique_xmalloc_ptr<char> name_holder;
+ std::string name_holder;
const char *include_name =
psymtab_include_file_name (lh, file_entry, pst,
- comp_dir, &name_holder);
+ comp_dir, name_holder);
if (include_name != NULL)
dwarf2_create_include_psymtab (include_name, pst, objfile);
}
@@ -21360,7 +21356,7 @@ static void
dwarf2_start_subfile (struct dwarf2_cu *cu, const char *filename,
const char *dirname)
{
- gdb::unique_xmalloc_ptr<char> copy;
+ std::string copy;
/* In order not to lose the line information directory,
we concatenate it to the filename when it makes sense.
@@ -21371,8 +21367,8 @@ dwarf2_start_subfile (struct dwarf2_cu *cu, const char *filename,
if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
{
- copy.reset (concat (dirname, SLASH_STRING, filename, (char *) NULL));
- filename = copy.get ();
+ copy = path_join (dirname, filename);
+ filename = copy.c_str ();
}
cu->get_builder ()->start_subfile (filename);
diff --git a/gdb/macrotab.c b/gdb/macrotab.c
--- a/gdb/macrotab.c
+++ b/gdb/macrotab.c
@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
+#include "gdbsupport/pathstuff.h"
#include "gdb_obstack.h"
#include "splay-tree.h"
#include "filenames.h"
@@ -1071,5 +1072,5 @@ macro_source_fullname (struct macro_source_file *file)
if (comp_dir == NULL || IS_ABSOLUTE_PATH (file->filename))
return file->filename;
- return std::string (comp_dir) + SLASH_STRING + file->filename;
+ return path_join (comp_dir, file->filename);
}
diff --git a/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp b/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp
--- a/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp
+++ b/gdb/testsuite/gdb.mi/mi-fullname-deleted.exp
@@ -36,6 +36,12 @@ if { [regsub {^(/[^/]+)/} $srcfileabs {\1subst/} srcfileabssubst] != 1
return -1
}
+# Generate a regular expression which to match $srcfileabs with
+# or without the doubled slash. This is used by the substituted
+# fullname test.
+set srcfileabssubst_regexp [string_to_regexp $srcfileabssubst]
+regsub {//} $srcfileabssubst_regexp {\0?} srcfileabssubst_regexp
+
set f [open $srcfileabs "w"]
puts $f "int main (void) { return 0; }"
close $f
@@ -54,7 +60,7 @@ mi_gdb_test "-interpreter-exec console \"set substitute-path ${initdir} ${initdi
mi_gdb_test "-file-list-exec-source-file" ".*\",fullname=\".*\".*" "fullname present"
-mi_gdb_test "-file-list-exec-source-file" ".*\",fullname=\"[string_to_regexp $srcfileabssubst]\".*" "substituted fullname"
+mi_gdb_test "-file-list-exec-source-file" ".*\",fullname=\"$srcfileabssubst_regexp\".*" "substituted fullname"
# Test compare_filenames_for_search does not falsely use absolute filename as
# a relative one.
diff --git a/gdb/unittests/path-join-selftests.c b/gdb/unittests/path-join-selftests.c
new file mode 100644
--- /dev/null
+++ b/gdb/unittests/path-join-selftests.c
@@ -0,0 +1,73 @@
+/* Self tests for path_join for GDB, the GNU debugger.
+
+ Copyright (C) 2022 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "gdbsupport/pathstuff.h"
+#include "gdbsupport/selftest.h"
+
+namespace selftests {
+namespace path_join {
+
+template <typename ...Args>
+static void
+test_one (const char *expected, Args... paths)
+{
+ std::string actual = ::path_join (paths...);
+
+ SELF_CHECK (actual == expected);
+}
+
+/* Test path_join. */
+
+static void
+test ()
+{
+ test_one ("/foo/bar", "/foo", "bar");
+ test_one ("/bar", "/", "bar");
+ test_one ("foo/bar/", "foo", "bar", "");
+ test_one ("foo", "", "foo");
+ test_one ("foo/bar", "foo", "", "bar");
+ test_one ("foo/", "foo", "");
+ test_one ("foo/", "foo/", "");
+
+ test_one ("D:/foo/bar", "D:/foo", "bar");
+ test_one ("D:/foo/bar", "D:/foo/", "bar");
+
+#if defined(_WIN32)
+ /* The current implementation doesn't recognize backslashes as directory
+ separators on Unix-like systems, so only run these tests on Windows. If
+ we ever switch our implementation to use std::filesystem::path, they
+ should work anywhere, in theory. */
+ test_one ("D:\\foo/bar", "D:\\foo", "bar");
+ test_one ("D:\\foo\\bar", "D:\\foo\\", "bar");
+ test_one ("\\\\server\\dir\\file", "\\\\server\\dir\\", "file");
+ test_one ("\\\\server\\dir/file", "\\\\server\\dir", "file");
+#endif /* _WIN32 */
+}
+
+}
+}
+
+void _initialize_path_join_selftests ();
+void
+_initialize_path_join_selftests ()
+{
+ selftests::register_test ("path_join",
+ selftests::path_join::test);
+}
diff --git a/gdbsupport/pathstuff.cc b/gdbsupport/pathstuff.cc
--- a/gdbsupport/pathstuff.cc
+++ b/gdbsupport/pathstuff.cc
@@ -87,7 +87,6 @@ gdb_realpath_keepfile (const char *filename)
{
const char *base_name = lbasename (filename);
char *dir_name;
- char *result;
/* Extract the basename of filename, and return immediately
a copy of filename if it does not contain any directory prefix. */
@@ -116,12 +115,7 @@ gdb_realpath_keepfile (const char *filename)
directory separator, avoid doubling it. */
gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
const char *real_path = path_storage.get ();
- if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1]))
- result = concat (real_path, base_name, (char *) NULL);
- else
- result = concat (real_path, SLASH_STRING, base_name, (char *) NULL);
-
- return gdb::unique_xmalloc_ptr<char> (result);
+ return make_unique_xstrdup (path_join (real_path, base_name).c_str ());
}
/* See gdbsupport/pathstuff.h. */
@@ -137,12 +131,7 @@ gdb_abspath (const char *path)
if (IS_ABSOLUTE_PATH (path) || current_directory == NULL)
return path;
- /* Beware the // my son, the Emacs barfs, the botch that catch... */
- return string_printf
- ("%s%s%s", current_directory,
- (IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1])
- ? "" : SLASH_STRING),
- path);
+ return path_join (current_directory, path);
}
/* See gdbsupport/pathstuff.h. */
@@ -197,6 +186,29 @@ child_path (const char *parent, const char *child)
/* See gdbsupport/pathstuff.h. */
+std::string
+path_join (gdb::array_view<const gdb::string_view> paths)
+{
+ std::string ret;
+
+ for (int i = 0; i < paths.size (); ++i)
+ {
+ const gdb::string_view path = paths[i];
+
+ if (i > 0)
+ gdb_assert (!IS_ABSOLUTE_PATH (path));
+
+ if (!ret.empty () && !IS_DIR_SEPARATOR (ret.back ()))
+ ret += '/';
+
+ ret.append (path.begin (), path.end ());
+ }
+
+ return ret;
+}
+
+/* See gdbsupport/pathstuff.h. */
+
bool
contains_dir_separator (const char *path)
{
@@ -226,7 +238,7 @@ get_standard_cache_dir ()
{
/* Make sure the path is absolute and tilde-expanded. */
std::string abs = gdb_abspath (xdg_cache_home);
- return string_printf ("%s/gdb", abs.c_str ());
+ return path_join (abs.c_str (), "gdb");
}
#endif
@@ -235,7 +247,7 @@ get_standard_cache_dir ()
{
/* Make sure the path is absolute and tilde-expanded. */
std::string abs = gdb_abspath (home);
- return string_printf ("%s/" HOME_CACHE_DIR "/gdb", abs.c_str ());
+ return path_join (abs.c_str (), HOME_CACHE_DIR, "gdb");
}
return {};
diff --git a/gdbsupport/pathstuff.h b/gdbsupport/pathstuff.h
--- a/gdbsupport/pathstuff.h
+++ b/gdbsupport/pathstuff.h
@@ -21,6 +21,7 @@
#define COMMON_PATHSTUFF_H
#include "gdbsupport/byte-vector.h"
+#include "gdbsupport/array-view.h"
/* Path utilities. */
@@ -57,6 +58,28 @@ extern std::string gdb_abspath (const char *path);
extern const char *child_path (const char *parent, const char *child);
+/* Join elements in PATHS into a single path.
+
+ The first element can be absolute or relative. All the others must be
+ relative. */
+
+extern std::string path_join (gdb::array_view<const gdb::string_view> paths);
+
+/* Same as the above, but accept paths as distinct parameters. */
+
+template<typename ...Args>
+std::string
+path_join (Args... paths)
+{
+ /* It doesn't make sense to join less than two paths. */
+ gdb_static_assert (sizeof... (Args) >= 2);
+
+ std::array<gdb::string_view, sizeof... (Args)> views
+ { gdb::string_view (paths)... };
+
+ return path_join (gdb::array_view<const gdb::string_view> (views));
+}
+
/* Return whether PATH contains a directory separator character. */
extern bool contains_dir_separator (const char *path);

@ -0,0 +1,47 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Keith Seitz <keiths@redhat.com>
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-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
with std::string::back, which results in undefined behaviour. A typical
use case where this can happen is when the root directory "/" is used as
a compilation directory.
With libstdc++.so.6.0.28 we get no out-of-bounds checks and the byte
preceding the storage of the empty string is returned. The character
value of this byte depends on heap implementation and usage, but when
this byte happens to hold the value of the directory separator character
we go on to call std::string::pop_back on the empty string which results
in an out_of_range exception which terminates GDB.
Fix this by using path_join. prepare_path_for_appending ensures that the
filename component is relative.
The testsuite has been run before and after the change and no
regressions were found.
diff --git a/gdb/source.c b/gdb/source.c
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -1111,15 +1111,7 @@ find_and_open_source (const char *filename,
helpful if part of the compilation directory was removed,
e.g. using gcc's -fdebug-prefix-map, and we have added the missing
prefix to source_path. */
- std::string cdir_filename (dirname);
-
- /* Remove any trailing directory separators. */
- while (IS_DIR_SEPARATOR (cdir_filename.back ()))
- cdir_filename.pop_back ();
-
- /* Add our own directory separator. */
- cdir_filename.append (SLASH_STRING);
- cdir_filename.append (filename_start);
+ std::string cdir_filename = path_join (dirname, filename_start);
result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH,
cdir_filename.c_str (), OPEN_MODE, fullname);

@ -0,0 +1,113 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Keith Seitz <keiths@redhat.com>
Date: Wed, 6 Dec 2023 07:19:49 -0800
Subject: gdb-find_and_open_source-empty-string-ub-4of4.patch
;; Backport "gdbsupport: change path_join parameter to
;; array_view<const char *>"
;; (Simon Marchi)
When a GDB built with -D_GLIBCXX_DEBUG=1 reads a binary with a single
character name, we hit this assertion failure:
$ ./gdb -q --data-directory=data-directory -nx ./x
/usr/include/c++/12.1.0/string_view:239: constexpr const std::basic_string_view<_CharT, _Traits>::value_type& std::basic_string_view<_CharT, _Traits>::operator[](size_type) const [with _CharT = char; _Traits = std::char_traits<char>; const_reference = const char&; size_type = long unsigned int]: Assertion '__pos < this->_M_len' failed.
The backtrace:
#3 0x00007ffff6c0f002 in std::__glibcxx_assert_fail (file=<optimized out>, line=<optimized out>, function=<optimized out>, condition=<optimized out>) at /usr/src/debug/gcc/libstdc++-v3/src/c++11/debug.cc:60
#4 0x000055555da8a864 in std::basic_string_view<char, std::char_traits<char> >::operator[] (this=0x7fffffffcc30, __pos=1) at /usr/include/c++/12.1.0/string_view:239
#5 0x00005555609dcb88 in path_join[abi:cxx11](gdb::array_view<std::basic_string_view<char, std::char_traits<char> > const>) (paths=...) at /home/simark/src/binutils-gdb/gdbsupport/pathstuff.cc:203
#6 0x000055555e0443f4 in path_join<char const*, char const*> () at /home/simark/src/binutils-gdb/gdb/../gdbsupport/pathstuff.h:84
#7 0x00005555609dc336 in gdb_realpath_keepfile[abi:cxx11](char const*) (filename=0x6060000a8d40 "/home/simark/build/binutils-gdb-one-target/gdb/./x") at /home/simark/src/binutils-gdb/gdbsupport/pathstuff.cc:122
#8 0x000055555ebd2794 in exec_file_attach (filename=0x7fffffffe0f9 "./x", from_tty=1) at /home/simark/src/binutils-gdb/gdb/exec.c:471
#9 0x000055555f2b3fb0 in catch_command_errors (command=0x55555ebd1ab6 <exec_file_attach(char const*, int)>, arg=0x7fffffffe0f9 "./x", from_tty=1, do_bp_actions=false) at /home/simark/src/binutils-gdb/gdb/main.c:513
#10 0x000055555f2b7e11 in captured_main_1 (context=0x7fffffffdb60) at /home/simark/src/binutils-gdb/gdb/main.c:1209
#11 0x000055555f2b9144 in captured_main (data=0x7fffffffdb60) at /home/simark/src/binutils-gdb/gdb/main.c:1319
#12 0x000055555f2b9226 in gdb_main (args=0x7fffffffdb60) at /home/simark/src/binutils-gdb/gdb/main.c:1344
#13 0x000055555d938c5e in main (argc=5, argv=0x7fffffffdcf8) at /home/simark/src/binutils-gdb/gdb/gdb.c:32
The problem is this line in path_join:
gdb_assert (strlen (path) == 0 || !IS_ABSOLUTE_PATH (path));
... where `path` is "x". IS_ABSOLUTE_PATH eventually calls
HAS_DRIVE_SPEC_1:
#define HAS_DRIVE_SPEC_1(dos_based, f) \
((f)[0] && ((f)[1] == ':') && (dos_based))
This macro accesses indices 0 and 1 of the input string. However, `f`
is a string_view of length 1, so it's incorrect to try to access index
1. We know that the string_view's underlying object is a null-terminated
string, so in practice there's no harm. But as far as the string_view
is concerned, index 1 is considered out of bounds.
This patch makes the easy fix, that is to change the path_join parameter
from a vector of to a vector of `const char *`. Another solution would
be to introduce a non-standard gdb::cstring_view class, which would be a
view over a null-terminated string. With that class, it would be
correct to access index 1, it would yield the NUL character. If there
is interest in having this class (it has been mentioned a few times in
the past) I can do it and use it here.
This was found by running tests such as gdb.ada/arrayidx.exp, which
produce 1-char long filenames, so adding a new test is not necessary.
Change-Id: Ia41a16c7243614636b18754fd98a41860756f7af
diff --git a/gdbsupport/pathstuff.cc b/gdbsupport/pathstuff.cc
--- a/gdbsupport/pathstuff.cc
+++ b/gdbsupport/pathstuff.cc
@@ -187,21 +187,21 @@ child_path (const char *parent, const char *child)
/* See gdbsupport/pathstuff.h. */
std::string
-path_join (gdb::array_view<const gdb::string_view> paths)
+path_join (gdb::array_view<const char *> paths)
{
std::string ret;
for (int i = 0; i < paths.size (); ++i)
{
- const gdb::string_view path = paths[i];
+ const char *path = paths[i];
if (i > 0)
- gdb_assert (!IS_ABSOLUTE_PATH (path));
+ gdb_assert (strlen (path) == 0 || !IS_ABSOLUTE_PATH (path));
if (!ret.empty () && !IS_DIR_SEPARATOR (ret.back ()))
ret += '/';
- ret.append (path.begin (), path.end ());
+ ret.append (path);
}
return ret;
diff --git a/gdbsupport/pathstuff.h b/gdbsupport/pathstuff.h
--- a/gdbsupport/pathstuff.h
+++ b/gdbsupport/pathstuff.h
@@ -63,7 +63,7 @@ extern const char *child_path (const char *parent, const char *child);
The first element can be absolute or relative. All the others must be
relative. */
-extern std::string path_join (gdb::array_view<const gdb::string_view> paths);
+extern std::string path_join (gdb::array_view<const char *> paths);
/* Same as the above, but accept paths as distinct parameters. */
@@ -74,10 +74,10 @@ path_join (Args... paths)
/* It doesn't make sense to join less than two paths. */
gdb_static_assert (sizeof... (Args) >= 2);
- std::array<gdb::string_view, sizeof... (Args)> views
- { gdb::string_view (paths)... };
+ std::array<const char *, sizeof... (Args)> path_array
+ { paths... };
- return path_join (gdb::array_view<const gdb::string_view> (views));
+ return path_join (gdb::array_view<const char *> (path_array));
}
/* Return whether PATH contains a directory separator character. */

@ -0,0 +1,259 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Tom Tromey <tom@tromey.com>
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 <aburgess@redhat.com>
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 <http://www.gnu.org/licenses/>. */
+
+/* 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 <http://www.gnu.org/licenses/>.
+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"

@ -0,0 +1,119 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Nick Clifton <nickc@redhat.com>
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). */

@ -0,0 +1,85 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Nick Clifton <nickc@redhat.com>
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

@ -0,0 +1,23 @@
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Nick Clifton <nickc@redhat.com>
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;

@ -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%{?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,7 +1158,23 @@ fi
%endif
%changelog
* Fri Sep 22 2023 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 10.2-11
* Wed Dec 13 2023 Keith Seitz - 10.2-13.el9
- Backport patches for "Fix undefined behaviour dereferencing empty string"
(Magne Hov et al, RHEL-17631)
* Tue Oct 3 2023 Guinevere Larsen <blarsen@redhat.com> - 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 <blarsen@redhat.com>
- Backport "Fix crash in Fortran code"
(Tom Tromey, RHEL-7328)
* Fri Sep 22 2023 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 10.2-11.el9
- Rebuilt for MSVSphere 9.3 beta
* Wed Mar 29 2023 Bruno Larsen <blarsen@redhat.com> - 10.2-11.el9
@ -1169,7 +1185,7 @@ fi
- Backport "[gdb/breakpoint] Fix assert in jit_event_handler"
(Tom de Vries, RHBZ 2130624)
* Wed Mar 23 2023 Bruno Larsen <blarsen@redhat.com>
* Thu Mar 23 2023 Bruno Larsen <blarsen@redhat.com>
- Bakport "Fix assertion failure in copy_type"
(Tom Tromey, RHBZ 2155439)
- Bakport "[gdb/testsuite] Fix PR20630 regression test in gdb.base/printcmds.exp"

Loading…
Cancel
Save