[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