| From 37dea6b8efeacf1b85f975eaa848ce7312e26379 Mon Sep 17 00:00:00 2001 |
| From: Alan Modra <amodra@gmail.com> |
| Date: Wed, 15 Dec 2021 11:48:42 +1030 |
| Subject: [PATCH] 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. |
| --- |
| binutils/stabs.c | 87 ++++++++++++++++++++++++------------------------ |
| 1 file changed, 43 insertions(+), 44 deletions(-) |
| |
| diff --git a/binutils/stabs.c b/binutils/stabs.c |
| index 90254fdb2a6..d430d4a1678 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 bfd_boolean 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; |
| } |
| |
| -- |
| 2.34.1 |
| |