]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Avoid crash in dwarf2/read.c:determine_prefix
authorTom Tromey <tromey@adacore.com>
Tue, 21 Apr 2026 20:03:39 +0000 (14:03 -0600)
committerTom Tromey <tromey@adacore.com>
Fri, 1 May 2026 16:17:36 +0000 (10:17 -0600)
I found a gdb crash when using some changes to gnat-llvm to have it
emit unqualified names in the DWARF.  The crash happens because
determine_prefix does this:

  return dwarf2_full_name (nullptr, parent, cu);

However, dwarf2_full_name can return NULL, causing a crash in the
caller.

The particular DWARF causing this is pretty strange -- it is a
function nested inside another nameless function.  This may be a bug
in gnat-llvm, something I plan to investigate.

Meanwhile, gdb shouldn't crash.  This patch changes determine_prefix
to avoid possible crashes here, by following its contract and not
returning NULL.

I'm not sure if it's worthwhile to write a test case for this.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
gdb/dwarf2/read.c

index 1288c076aba10381b838ba621ff721d69f7218ca..7b5e1b65554ec2a7ee7325ea5dc22d5f758af1d2 100644 (file)
@@ -16637,23 +16637,28 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
          }
        return "";
       case DW_TAG_subprogram:
-       /* Nested subroutines in Fortran get a prefix with the name
-          of the parent's subroutine.  Entry points are prefixed by the
-          parent's namespace.  */
-       if (cu->lang () == language_fortran)
-         {
-           if ((die->tag ==  DW_TAG_subprogram)
-               && (dwarf2_name (parent, cu) != NULL))
-             return dwarf2_name (parent, cu);
-           else if (die->tag == DW_TAG_entry_point)
-             return determine_prefix (parent, cu);
-         }
-       else if (cu->lang () == language_ada
-                && (die->tag == DW_TAG_subprogram
-                    || die->tag == DW_TAG_inlined_subroutine
-                    || die->tag == DW_TAG_lexical_block))
-         return dwarf2_full_name (nullptr, parent, cu);
-       return "";
+       {
+         const char *name = nullptr;
+         /* Nested subroutines in Fortran get a prefix with the name
+            of the parent's subroutine.  Entry points are prefixed by the
+            parent's namespace.  */
+         if (cu->lang () == language_fortran)
+           {
+             if ((die->tag ==  DW_TAG_subprogram)
+                 && (dwarf2_name (parent, cu) != NULL))
+               name = dwarf2_name (parent, cu);
+             else if (die->tag == DW_TAG_entry_point)
+               name = determine_prefix (parent, cu);
+           }
+         else if (cu->lang () == language_ada
+                  && (die->tag == DW_TAG_subprogram
+                      || die->tag == DW_TAG_inlined_subroutine
+                      || die->tag == DW_TAG_lexical_block))
+           name = dwarf2_full_name (nullptr, parent, cu);
+         if (name == nullptr)
+           name = "";
+         return name;
+       }
       case DW_TAG_enumeration_type:
        parent_type = read_type_die (parent, cu);
        if (parent_type->is_declared_class ())