[PATCH] binutils: fix stack-overflow in debug_write_type [BZ #28718]

Pavel Mayorov pmayorov@cloudlinux.com
Mon Dec 20 19:44:28 GMT 2021


I found a stack-overflow in 'debug_write_type' (binutils/debug.c).
The problem is caused by a self-reference in a type definition string
in the "stabs" representation of debugging information
(http://www.sourceware.org/gdb/onlinedocs/stabs.html).
This leads to an infinite recursion during the printing debug
information about this type.

There is the following type definition:
    .stabs "some_type:t&1=2=3=2",128,0,0,0
Here 'some_type' is defined as a reference to the indirect type 1,
which is the indirect type 2, which is the indirect type 3, which
finally is the indirect type 2. And after parsing we get a "looped"
type 2:
    *type->u.kindirect->slot == type

To solve this problem, it is enough to check this situation and mark
this type as undefined.
---
 binutils/debug.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/binutils/debug.c b/binutils/debug.c
index 9d60d154f04..b2a48f642ae 100644
--- a/binutils/debug.c
+++ b/binutils/debug.c
@@ -2065,7 +2065,9 @@ debug_get_real_type (void *handle, debug_type type,
       /* The default case is just here to avoid warnings.  */
     default:
     case DEBUG_KIND_INDIRECT:
-      if (*type->u.kindirect->slot != NULL)
+      /* A valid non-self-referencing indirect type.  */
+      if (*type->u.kindirect->slot != NULL
+   && *type->u.kindirect->slot != type)
  return debug_get_real_type (handle, *type->u.kindirect->slot, &rl);
       return type;
     case DEBUG_KIND_NAMED:
@@ -2095,7 +2097,9 @@ debug_get_type_name (void *handle, debug_type type)
 {
   if (type->kind == DEBUG_KIND_INDIRECT)
     {
-      if (*type->u.kindirect->slot != NULL)
+      /* A valid non-self-referencing indirect type.  */
+      if (*type->u.kindirect->slot != NULL
+   && *type->u.kindirect->slot != type)
  return debug_get_type_name (handle, *type->u.kindirect->slot);
       return type->u.kindirect->tag;
     }
@@ -2124,7 +2128,9 @@ debug_get_type_size (void *handle, debug_type type)
     default:
       return 0;
     case DEBUG_KIND_INDIRECT:
-      if (*type->u.kindirect->slot != NULL)
+      /* A valid non-self-referencing indirect type.  */
+      if (*type->u.kindirect->slot != NULL
+   && *type->u.kindirect->slot != type)
  return debug_get_type_size (handle, *type->u.kindirect->slot);
       return 0;
     case DEBUG_KIND_NAMED:
@@ -2484,6 +2490,9 @@ debug_write_type (struct debug_handle *info,
       debug_error (_("debug_write_type: illegal type encountered"));
       return false;
     case DEBUG_KIND_INDIRECT:
+      /* Prevent infinite recursion.  */
+      if (*type->u.kindirect->slot == type)
+ return (*fns->empty_type) (fhandle);
       return debug_write_type (info, fns, fhandle, *type->u.kindirect->slot,
         name);
     case DEBUG_KIND_VOID:
-- 
2.25.1


More information about the Binutils mailing list