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
(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;
}