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.
This commit is contained in:
Alan Modra 2021-12-15 11:48:42 +10:30
parent d5c9473176
commit 161e87d121

View file

@ -202,7 +202,7 @@ static debug_type stab_find_type (void *, struct stab_handle *, const int *);
static bool stab_record_type static bool stab_record_type
(void *, struct stab_handle *, const int *, debug_type); (void *, struct stab_handle *, const int *, debug_type);
static debug_type stab_xcoff_builtin_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 static debug_type stab_find_tagged_type
(void *, struct stab_handle *, const char *, int, enum debug_type_kind); (void *, struct stab_handle *, const char *, int, enum debug_type_kind);
static debug_type *stab_demangle_argtypes static debug_type *stab_demangle_argtypes
@ -3496,166 +3496,167 @@ stab_record_type (void *dhandle ATTRIBUTE_UNUSED, struct stab_handle *info,
static debug_type static debug_type
stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info, stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
int typenum) unsigned int typenum)
{ {
debug_type rettype; debug_type rettype;
const char *name; 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; return DEBUG_TYPE_NULL;
} }
if (info->xcoff_types[-typenum] != NULL) if (info->xcoff_types[typenum] != NULL)
return info->xcoff_types[-typenum]; 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 /* The size of this and all the other types are fixed, defined
by the debugging format. */ by the debugging format. */
name = "int"; name = "int";
rettype = debug_make_int_type (dhandle, 4, false); rettype = debug_make_int_type (dhandle, 4, false);
break; break;
case 2: case 1:
name = "char"; name = "char";
rettype = debug_make_int_type (dhandle, 1, false); rettype = debug_make_int_type (dhandle, 1, false);
break; break;
case 3: case 2:
name = "short"; name = "short";
rettype = debug_make_int_type (dhandle, 2, false); rettype = debug_make_int_type (dhandle, 2, false);
break; break;
case 4: case 3:
name = "long"; name = "long";
rettype = debug_make_int_type (dhandle, 4, false); rettype = debug_make_int_type (dhandle, 4, false);
break; break;
case 5: case 4:
name = "unsigned char"; name = "unsigned char";
rettype = debug_make_int_type (dhandle, 1, true); rettype = debug_make_int_type (dhandle, 1, true);
break; break;
case 6: case 5:
name = "signed char"; name = "signed char";
rettype = debug_make_int_type (dhandle, 1, false); rettype = debug_make_int_type (dhandle, 1, false);
break; break;
case 7: case 6:
name = "unsigned short"; name = "unsigned short";
rettype = debug_make_int_type (dhandle, 2, true); rettype = debug_make_int_type (dhandle, 2, true);
break; break;
case 8: case 7:
name = "unsigned int"; name = "unsigned int";
rettype = debug_make_int_type (dhandle, 4, true); rettype = debug_make_int_type (dhandle, 4, true);
break; break;
case 9: case 8:
name = "unsigned"; name = "unsigned";
rettype = debug_make_int_type (dhandle, 4, true); rettype = debug_make_int_type (dhandle, 4, true);
break; break;
case 10: case 9:
name = "unsigned long"; name = "unsigned long";
rettype = debug_make_int_type (dhandle, 4, true); rettype = debug_make_int_type (dhandle, 4, true);
break; break;
case 11: case 10:
name = "void"; name = "void";
rettype = debug_make_void_type (dhandle); rettype = debug_make_void_type (dhandle);
break; break;
case 12: case 11:
/* IEEE single precision (32 bit). */ /* IEEE single precision (32 bit). */
name = "float"; name = "float";
rettype = debug_make_float_type (dhandle, 4); rettype = debug_make_float_type (dhandle, 4);
break; break;
case 13: case 12:
/* IEEE double precision (64 bit). */ /* IEEE double precision (64 bit). */
name = "double"; name = "double";
rettype = debug_make_float_type (dhandle, 8); rettype = debug_make_float_type (dhandle, 8);
break; break;
case 14: case 13:
/* This is an IEEE double on the RS/6000, and different machines /* This is an IEEE double on the RS/6000, and different machines
with different sizes for "long double" should use different with different sizes for "long double" should use different
negative type numbers. See stabs.texinfo. */ negative type numbers. See stabs.texinfo. */
name = "long double"; name = "long double";
rettype = debug_make_float_type (dhandle, 8); rettype = debug_make_float_type (dhandle, 8);
break; break;
case 15: case 14:
name = "integer"; name = "integer";
rettype = debug_make_int_type (dhandle, 4, false); rettype = debug_make_int_type (dhandle, 4, false);
break; break;
case 16: case 15:
name = "boolean"; name = "boolean";
rettype = debug_make_bool_type (dhandle, 4); rettype = debug_make_bool_type (dhandle, 4);
break; break;
case 17: case 16:
name = "short real"; name = "short real";
rettype = debug_make_float_type (dhandle, 4); rettype = debug_make_float_type (dhandle, 4);
break; break;
case 18: case 17:
name = "real"; name = "real";
rettype = debug_make_float_type (dhandle, 8); rettype = debug_make_float_type (dhandle, 8);
break; break;
case 19: case 18:
/* FIXME */ /* FIXME */
name = "stringptr"; name = "stringptr";
rettype = NULL; rettype = NULL;
break; break;
case 20: case 19:
/* FIXME */ /* FIXME */
name = "character"; name = "character";
rettype = debug_make_int_type (dhandle, 1, true); rettype = debug_make_int_type (dhandle, 1, true);
break; break;
case 21: case 20:
name = "logical*1"; name = "logical*1";
rettype = debug_make_bool_type (dhandle, 1); rettype = debug_make_bool_type (dhandle, 1);
break; break;
case 22: case 21:
name = "logical*2"; name = "logical*2";
rettype = debug_make_bool_type (dhandle, 2); rettype = debug_make_bool_type (dhandle, 2);
break; break;
case 23: case 22:
name = "logical*4"; name = "logical*4";
rettype = debug_make_bool_type (dhandle, 4); rettype = debug_make_bool_type (dhandle, 4);
break; break;
case 24: case 23:
name = "logical"; name = "logical";
rettype = debug_make_bool_type (dhandle, 4); rettype = debug_make_bool_type (dhandle, 4);
break; break;
case 25: case 24:
/* Complex type consisting of two IEEE single precision values. */ /* Complex type consisting of two IEEE single precision values. */
name = "complex"; name = "complex";
rettype = debug_make_complex_type (dhandle, 8); rettype = debug_make_complex_type (dhandle, 8);
break; break;
case 26: case 25:
/* Complex type consisting of two IEEE double precision values. */ /* Complex type consisting of two IEEE double precision values. */
name = "double complex"; name = "double complex";
rettype = debug_make_complex_type (dhandle, 16); rettype = debug_make_complex_type (dhandle, 16);
break; break;
case 27: case 26:
name = "integer*1"; name = "integer*1";
rettype = debug_make_int_type (dhandle, 1, false); rettype = debug_make_int_type (dhandle, 1, false);
break; break;
case 28: case 27:
name = "integer*2"; name = "integer*2";
rettype = debug_make_int_type (dhandle, 2, false); rettype = debug_make_int_type (dhandle, 2, false);
break; break;
case 29: case 28:
name = "integer*4"; name = "integer*4";
rettype = debug_make_int_type (dhandle, 4, false); rettype = debug_make_int_type (dhandle, 4, false);
break; break;
case 30: case 29:
/* FIXME */ /* FIXME */
name = "wchar"; name = "wchar";
rettype = debug_make_int_type (dhandle, 2, false); rettype = debug_make_int_type (dhandle, 2, false);
break; break;
case 31: case 30:
name = "long long"; name = "long long";
rettype = debug_make_int_type (dhandle, 8, false); rettype = debug_make_int_type (dhandle, 8, false);
break; break;
case 32: case 31:
name = "unsigned long long"; name = "unsigned long long";
rettype = debug_make_int_type (dhandle, 8, true); rettype = debug_make_int_type (dhandle, 8, true);
break; break;
case 33: case 32:
name = "logical*8"; name = "logical*8";
rettype = debug_make_bool_type (dhandle, 8); rettype = debug_make_bool_type (dhandle, 8);
break; break;
case 34: case 33:
name = "integer*8"; name = "integer*8";
rettype = debug_make_int_type (dhandle, 8, false); rettype = debug_make_int_type (dhandle, 8, false);
break; break;
@ -3664,9 +3665,7 @@ stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
} }
rettype = debug_name_type (dhandle, name, rettype); rettype = debug_name_type (dhandle, name, rettype);
info->xcoff_types[typenum] = rettype;
info->xcoff_types[-typenum] = rettype;
return rettype; return rettype;
} }