[binutils-gdb] Throw error when creating an overly large gdb-index file

Kevin Buettner kevinb@sourceware.org
Thu Sep 14 23:53:00 GMT 2023


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=98f6baad7c31ab930cc911f1b127906eaf41d0ad

commit 98f6baad7c31ab930cc911f1b127906eaf41d0ad
Author: Kevin Buettner <kevinb@redhat.com>
Date:   Fri Sep 8 18:15:53 2023 -0700

    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:
---
 gdb/dwarf2/index-write.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index 11f254e263a..3827a810130 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -1083,7 +1083,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);
@@ -1110,6 +1110,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);


More information about the Gdb-cvs mailing list