123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- From: Alan Modra <amodra@gmail.com>
- Date: Wed, 15 Dec 2021 01:18:42 +0000 (+1030)
- Subject: PR28694, Out-of-bounds write in stab_xcoff_builtin_type
- CVE: CVE-2021-45078
- Upstream-Status: Backport [https://sourceware.org/git/?p=binutils-gdb.git;a=commitdiff_plain;h=161e87d12167b1e36193385485c1f6ce92f74f02]
- 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;
- }
-
|