From: Alan Modra Date: Wed, 15 Dec 2021 01:18:42 +0000 (+1030) Subject: PR28694, Out-of-bounds write in stab_xcoff_builtin_type X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=161e87d12167b1e36193385485c1f6ce92f74f02;p=binutils-gdb.git PR28694, Out-of-bounds write in stab_xcoff_builtin_type PR 28694 * stabs.c (stab_xcoff_builtin_type): Make typenum unsigned. Negate typenum earlier, simplifying bounds checking. Correct off-by-one indexing. Adjust switch cases. --- diff --git a/binutils/stabs.c b/binutils/stabs.c index 274bfb0e7fa..83ee3ea5fa4 100644 --- a/binutils/stabs.c +++ b/binutils/stabs.c @@ -202,7 +202,7 @@ static debug_type stab_find_type (void *, struct stab_handle *, const int *); static bool stab_record_type (void *, struct stab_handle *, const int *, debug_type); static debug_type stab_xcoff_builtin_type - (void *, struct stab_handle *, int); + (void *, struct stab_handle *, unsigned int); static debug_type stab_find_tagged_type (void *, struct stab_handle *, const char *, int, enum debug_type_kind); static debug_type *stab_demangle_argtypes @@ -3496,166 +3496,167 @@ stab_record_type (void *dhandle ATTRIBUTE_UNUSED, struct stab_handle *info, static debug_type stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info, - int typenum) + unsigned int typenum) { debug_type rettype; const char *name; - if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT) + typenum = -typenum - 1; + if (typenum >= XCOFF_TYPE_COUNT) { - fprintf (stderr, _("Unrecognized XCOFF type %d\n"), typenum); + fprintf (stderr, _("Unrecognized XCOFF type %d\n"), -typenum - 1); return DEBUG_TYPE_NULL; } - if (info->xcoff_types[-typenum] != NULL) - return info->xcoff_types[-typenum]; + if (info->xcoff_types[typenum] != NULL) + return info->xcoff_types[typenum]; - switch (-typenum) + switch (typenum) { - case 1: + case 0: /* The size of this and all the other types are fixed, defined by the debugging format. */ name = "int"; rettype = debug_make_int_type (dhandle, 4, false); break; - case 2: + case 1: name = "char"; rettype = debug_make_int_type (dhandle, 1, false); break; - case 3: + case 2: name = "short"; rettype = debug_make_int_type (dhandle, 2, false); break; - case 4: + case 3: name = "long"; rettype = debug_make_int_type (dhandle, 4, false); break; - case 5: + case 4: name = "unsigned char"; rettype = debug_make_int_type (dhandle, 1, true); break; - case 6: + case 5: name = "signed char"; rettype = debug_make_int_type (dhandle, 1, false); break; - case 7: + case 6: name = "unsigned short"; rettype = debug_make_int_type (dhandle, 2, true); break; - case 8: + case 7: name = "unsigned int"; rettype = debug_make_int_type (dhandle, 4, true); break; - case 9: + case 8: name = "unsigned"; rettype = debug_make_int_type (dhandle, 4, true); break; - case 10: + case 9: name = "unsigned long"; rettype = debug_make_int_type (dhandle, 4, true); break; - case 11: + case 10: name = "void"; rettype = debug_make_void_type (dhandle); break; - case 12: + case 11: /* IEEE single precision (32 bit). */ name = "float"; rettype = debug_make_float_type (dhandle, 4); break; - case 13: + case 12: /* IEEE double precision (64 bit). */ name = "double"; rettype = debug_make_float_type (dhandle, 8); break; - case 14: + case 13: /* This is an IEEE double on the RS/6000, and different machines with different sizes for "long double" should use different negative type numbers. See stabs.texinfo. */ name = "long double"; rettype = debug_make_float_type (dhandle, 8); break; - case 15: + case 14: name = "integer"; rettype = debug_make_int_type (dhandle, 4, false); break; - case 16: + case 15: name = "boolean"; rettype = debug_make_bool_type (dhandle, 4); break; - case 17: + case 16: name = "short real"; rettype = debug_make_float_type (dhandle, 4); break; - case 18: + case 17: name = "real"; rettype = debug_make_float_type (dhandle, 8); break; - case 19: + case 18: /* FIXME */ name = "stringptr"; rettype = NULL; break; - case 20: + case 19: /* FIXME */ name = "character"; rettype = debug_make_int_type (dhandle, 1, true); break; - case 21: + case 20: name = "logical*1"; rettype = debug_make_bool_type (dhandle, 1); break; - case 22: + case 21: name = "logical*2"; rettype = debug_make_bool_type (dhandle, 2); break; - case 23: + case 22: name = "logical*4"; rettype = debug_make_bool_type (dhandle, 4); break; - case 24: + case 23: name = "logical"; rettype = debug_make_bool_type (dhandle, 4); break; - case 25: + case 24: /* Complex type consisting of two IEEE single precision values. */ name = "complex"; rettype = debug_make_complex_type (dhandle, 8); break; - case 26: + case 25: /* Complex type consisting of two IEEE double precision values. */ name = "double complex"; rettype = debug_make_complex_type (dhandle, 16); break; - case 27: + case 26: name = "integer*1"; rettype = debug_make_int_type (dhandle, 1, false); break; - case 28: + case 27: name = "integer*2"; rettype = debug_make_int_type (dhandle, 2, false); break; - case 29: + case 28: name = "integer*4"; rettype = debug_make_int_type (dhandle, 4, false); break; - case 30: + case 29: /* FIXME */ name = "wchar"; rettype = debug_make_int_type (dhandle, 2, false); break; - case 31: + case 30: name = "long long"; rettype = debug_make_int_type (dhandle, 8, false); break; - case 32: + case 31: name = "unsigned long long"; rettype = debug_make_int_type (dhandle, 8, true); break; - case 33: + case 32: name = "logical*8"; rettype = debug_make_bool_type (dhandle, 8); break; - case 34: + case 33: name = "integer*8"; rettype = debug_make_int_type (dhandle, 8, false); break; @@ -3664,9 +3665,7 @@ stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info, } rettype = debug_name_type (dhandle, name, rettype); - - info->xcoff_types[-typenum] = rettype; - + info->xcoff_types[typenum] = rettype; return rettype; }