File gdb-rhbz1773651-gdb-index-internal-error.patch of Package gdb.32332
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Kevin Buettner <kevinb@redhat.com>
Date: Mon, 2 Oct 2023 15:05:23 -0700
Subject: gdb-rhbz1773651-gdb-index-internal-error.patch
;; Backport upstream patch which prevents internal error when
;; generating a gdb-index file (RH BZ 1773651).
Throw error when creating an overly large gdb-index file
The header in a .gdb_index section uses 32-bit unsigned offsets to
refer to other areas of the section. Thus, there is a size limit of
2^32-1 which is currently unaccounted for by GDB's code for outputting
these sections.
At the moment, when GDB creates an overly large section, it will exit
abnormally due to an internal error, which is caused by a failed
assert in assert_file_size, which in turn is called from
write_gdbindex_1, both of which are in gdb/dwarf2/index-write.c.
This is what happens when that assert fails:
$ gdb -q -nx -iex 'set auto-load no' -iex 'set debuginfod enabled off' -ex file ./libgraph_tool_inference.so -ex "save gdb-index `pwd`/"
Reading symbols from ./libgraph_tool_inference.so...
No executable file now.
Discard symbol table from `libgraph_tool_inference.so'? (y or n) n
Not confirmed.
../../gdb/dwarf2/index-write.c:1069: internal-error: assert_file_size: Assertion `file_size == expected_size' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
----- Backtrace -----
0x55fddb4d78b0 gdb_internal_backtrace_1
../../gdb/bt-utils.c:122
0x55fddb4d78b0 _Z22gdb_internal_backtracev
../../gdb/bt-utils.c:168
0x55fddb98b5d4 internal_vproblem
../../gdb/utils.c:396
0x55fddb98b8de _Z15internal_verrorPKciS0_P13__va_list_tag
../../gdb/utils.c:476
0x55fddbb71654 _Z18internal_error_locPKciS0_z
../../gdbsupport/errors.cc:58
0x55fddb5a0f23 assert_file_size
../../gdb/dwarf2/index-write.c:1069
0x55fddb5a1ee0 assert_file_size
/usr/include/c++/13/bits/stl_iterator.h:1158
0x55fddb5a1ee0 write_gdbindex_1
../../gdb/dwarf2/index-write.c:1119
0x55fddb5a51be write_gdbindex
../../gdb/dwarf2/index-write.c:1273
[...]
---------------------
../../gdb/dwarf2/index-write.c:1069: internal-error: assert_file_size: Assertion `file_size == expected_size' failed.
This problem was encountered while building the python-graph-tool
package on Fedora. The Fedora bugzilla bug can be found here:
https://bugzilla.redhat.com/show_bug.cgi?id=1773651
This commit prevents the internal error from occurring by calling error()
when the file size exceeds 2^32-1.
Using a gdb built with this commit, I now see this behavior instead:
$ gdb -q -nx -iex 'set auto-load no' -iex 'set debuginfod enabled off' -ex file ./libgraph_tool_inference.so -ex "save gdb-index `pwd`/"
Reading symbols from ./libgraph_tool_inference.so...
No executable file now.
Discard symbol table from `/mesquite2/fedora-bugs/1773651/libgraph_tool_inference.so'? (y or n) n
Not confirmed.
Error while writing index for `/mesquite2/fedora-bugs/1773651/libgraph_tool_inference.so': gdb-index maximum file size of 4294967295 exceeded
(gdb)
I wish I could provide a test case, but due to the sizes of both the
input and output files, I think that testing resources would be
strained or exceeded in many environments.
My testing on Fedora 38 shows no regressions.
Approved-by: Tom Tromey <tom@tromey.com>
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -1082,7 +1082,7 @@ write_gdbindex_1 (FILE *out_file,
{
data_buf contents;
const offset_type size_of_header = 6 * sizeof (offset_type);
- offset_type total_len = size_of_header;
+ size_t total_len = size_of_header;
/* The version number. */
contents.append_offset (8);
@@ -1109,6 +1109,13 @@ write_gdbindex_1 (FILE *out_file,
gdb_assert (contents.size () == size_of_header);
+ /* The maximum size of an index file is limited by the maximum value
+ capable of being represented by 'offset_type'. Throw an error if
+ that length has been exceeded. */
+ size_t max_size = ~(offset_type) 0;
+ if (total_len > max_size)
+ error (_("gdb-index maximum file size of %zu exceeded"), max_size);
+
contents.file_write (out_file);
cu_list.file_write (out_file);
types_cu_list.file_write (out_file);