summaryrefslogtreecommitdiff
path: root/binutils/stabs.c
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2018-03-13 16:10:45 +0000
committerNick Clifton <nickc@redhat.com>2018-03-13 16:10:45 +0000
commit81db3241f2c888c4fae1884444953085be224815 (patch)
tree1b44453dfaf35d6a225e66be1b32bcd174d7b339 /binutils/stabs.c
parent3e33b239450771394fa6c83b67b9de80169f35e8 (diff)
downloadbinutils-gdb-81db3241f2c888c4fae1884444953085be224815.tar.gz
Add range changing to STABS parsing functions, in order to prevent buffer overruns.
PR 22955 * stabs.c (parse_number): Add p_end parameter and use it to check the validity of the pp parameter. Add checks to prevent walking off the end of the string buffer. (parse_stab_string): Likewise. (parse_stab_type): Likewise. (parse_stab_type_number): Likewise. (parse_stab_range_type): Likewise. (parse_stab_sun_builtin_type): Likewise. (parse_stab_sun_floating_type): Likewise. (parse_stab_enum_type): Likewise. (parse_stab_struct_type): Likewise. (parse_stab_baseclasses): Likewise. (parse_stab_struct_fields): Likewise. (parse_stab_cpp_abbrev): Likewise. (parse_stab_one_struct_field): Likewise. (parse_stab_members): Likewise. (parse_stab_tilde_field): Likewise. (parse_stab_array_type): Likewise. * parse_stab: Compute the end of the string and then pass it on to individual parser functions.
Diffstat (limited to 'binutils/stabs.c')
-rw-r--r--binutils/stabs.c404
1 files changed, 260 insertions, 144 deletions
diff --git a/binutils/stabs.c b/binutils/stabs.c
index a3ff3451d5a..807ca1e3c4a 100644
--- a/binutils/stabs.c
+++ b/binutils/stabs.c
@@ -145,42 +145,51 @@ struct stab_tag
};
static char *savestring (const char *, int);
-static bfd_vma parse_number (const char **, bfd_boolean *);
+
static void bad_stab (const char *);
static void warn_stab (const char *, const char *);
static bfd_boolean parse_stab_string
- (void *, struct stab_handle *, int, int, bfd_vma, const char *);
+ (void *, struct stab_handle *, int, int, bfd_vma,
+ const char *, const char *);
static debug_type parse_stab_type
- (void *, struct stab_handle *, const char *, const char **, debug_type **);
-static bfd_boolean parse_stab_type_number (const char **, int *);
+ (void *, struct stab_handle *, const char *, const char **,
+ debug_type **, const char *);
+static bfd_boolean parse_stab_type_number
+ (const char **, int *, const char *);
static debug_type parse_stab_range_type
- (void *, struct stab_handle *, const char *, const char **, const int *);
-static debug_type parse_stab_sun_builtin_type (void *, const char **);
-static debug_type parse_stab_sun_floating_type (void *, const char **);
-static debug_type parse_stab_enum_type (void *, const char **);
+ (void *, struct stab_handle *, const char *, const char **,
+ const int *, const char *);
+static debug_type parse_stab_sun_builtin_type
+ (void *, const char **, const char *);
+static debug_type parse_stab_sun_floating_type
+ (void *, const char **, const char *);
+static debug_type parse_stab_enum_type
+ (void *, const char **, const char *);
static debug_type parse_stab_struct_type
(void *, struct stab_handle *, const char *, const char **,
- bfd_boolean, const int *);
+ bfd_boolean, const int *, const char *);
static bfd_boolean parse_stab_baseclasses
- (void *, struct stab_handle *, const char **, debug_baseclass **);
+ (void *, struct stab_handle *, const char **, debug_baseclass **,
+ const char *);
static bfd_boolean parse_stab_struct_fields
- (void *, struct stab_handle *, const char **, debug_field **, bfd_boolean *);
+ (void *, struct stab_handle *, const char **, debug_field **,
+ bfd_boolean *, const char *);
static bfd_boolean parse_stab_cpp_abbrev
- (void *, struct stab_handle *, const char **, debug_field *);
+ (void *, struct stab_handle *, const char **, debug_field *, const char *);
static bfd_boolean parse_stab_one_struct_field
(void *, struct stab_handle *, const char **, const char *,
- debug_field *, bfd_boolean *);
+ debug_field *, bfd_boolean *, const char *);
static bfd_boolean parse_stab_members
(void *, struct stab_handle *, const char *, const char **, const int *,
- debug_method **);
+ debug_method **, const char *);
static debug_type parse_stab_argtypes
(void *, struct stab_handle *, debug_type, const char *, const char *,
debug_type, const char *, bfd_boolean, bfd_boolean, const char **);
static bfd_boolean parse_stab_tilde_field
(void *, struct stab_handle *, const char **, const int *, debug_type *,
- bfd_boolean *);
+ bfd_boolean *, const char *);
static debug_type parse_stab_array_type
- (void *, struct stab_handle *, const char **, bfd_boolean);
+ (void *, struct stab_handle *, const char **, bfd_boolean, const char *);
static void push_bincl (struct stab_handle *, const char *, bfd_vma);
static const char *pop_bincl (struct stab_handle *);
static bfd_boolean find_excl (struct stab_handle *, const char *, bfd_vma);
@@ -222,7 +231,7 @@ savestring (const char *start, int len)
/* Read a number from a string. */
static bfd_vma
-parse_number (const char **pp, bfd_boolean *poverflow)
+parse_number (const char **pp, bfd_boolean *poverflow, const char *p_end)
{
unsigned long ul;
const char *orig;
@@ -231,6 +240,8 @@ parse_number (const char **pp, bfd_boolean *poverflow)
*poverflow = FALSE;
orig = *pp;
+ if (orig >= p_end)
+ return (bfd_vma) 0;
/* Stop early if we are passed an empty string. */
if (*orig == 0)
@@ -409,6 +420,7 @@ bfd_boolean
parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
const char *string)
{
+ const char * string_end;
struct stab_handle *info = (struct stab_handle *) handle;
/* gcc will emit two N_SO strings per compilation unit, one for the
@@ -443,6 +455,8 @@ parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
/* Now process whatever type we just got. */
}
+ string_end = string + strlen (string);
+
switch (type)
{
case N_FN:
@@ -652,7 +666,7 @@ parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
info->within_function = TRUE;
}
- if (! parse_stab_string (dhandle, info, type, desc, value, string))
+ if (! parse_stab_string (dhandle, info, type, desc, value, string, string_end))
return FALSE;
}
break;
@@ -680,7 +694,8 @@ parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
static bfd_boolean
parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
- int desc ATTRIBUTE_UNUSED, bfd_vma value, const char *string)
+ int desc ATTRIBUTE_UNUSED, bfd_vma value,
+ const char *string, const char * string_end)
{
const char *p;
char *name;
@@ -743,6 +758,11 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
++p;
if (ISDIGIT (*p) || *p == '(' || *p == '-')
type = 'l';
+ else if (*p == 0)
+ {
+ bad_stab (string);
+ return FALSE;
+ }
else
type = *p++;
@@ -785,7 +805,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
e.g. "b:c=e6,0" for "const b = blob1"
(where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- &p, (debug_type **) NULL);
+ &p, (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (*p != ',')
@@ -806,7 +826,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'C':
/* The name of a caught exception. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- &p, (debug_type **) NULL);
+ &p, (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_label (dhandle, name, dtype, value))
@@ -817,7 +837,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'F':
/* A function definition. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
@@ -831,7 +851,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
{
++p;
if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL)
+ (debug_type **) NULL, string_end)
== DEBUG_TYPE_NULL)
return FALSE;
}
@@ -845,7 +865,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
/* A global symbol. The value must be extracted from the
symbol table. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (name != NULL)
@@ -881,7 +901,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'l':
case 's':
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
@@ -893,7 +913,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
/* A function parameter. */
if (*p != 'F')
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
else
{
/* pF is a two-letter code that means a function parameter in
@@ -901,7 +921,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
value. Translate it into a pointer-to-function type. */
++p;
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype != DEBUG_TYPE_NULL)
{
debug_type ftype;
@@ -931,7 +951,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
{
++p;
if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL)
+ (debug_type **) NULL, string_end)
== DEBUG_TYPE_NULL)
return FALSE;
}
@@ -941,7 +961,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'R':
/* Parameter which is in a register. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
@@ -952,7 +972,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'r':
/* Register variable (either global or local). */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
@@ -966,7 +986,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'S':
/* Static symbol at top level of file. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
@@ -976,7 +996,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 't':
/* A typedef. */
- dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+ dtype = parse_stab_type (dhandle, info, name, &p, &slot, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (name == NULL)
@@ -1009,7 +1029,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
++p;
}
- dtype = parse_stab_type (dhandle, info, name, &p, &slot);
+ dtype = parse_stab_type (dhandle, info, name, &p, &slot, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (name == NULL)
@@ -1060,7 +1080,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'V':
/* Static symbol of local scope */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
/* FIXME: gdb checks os9k_stabs here. */
@@ -1072,7 +1092,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'v':
/* Reference parameter. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
@@ -1083,7 +1103,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
case 'a':
/* Reference parameter which is in a register. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
@@ -1097,7 +1117,7 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
that Pascal uses it too, but when I tried it Pascal used
"x:3" (local symbol) instead. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
+ (debug_type **) NULL, string_end);
if (dtype == DEBUG_TYPE_NULL)
return FALSE;
if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
@@ -1142,7 +1162,12 @@ parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
store the slot used if the type is being defined. */
static debug_type
-parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name, const char **pp, debug_type **slotp)
+parse_stab_type (void * dhandle,
+ struct stab_handle * info,
+ const char * type_name,
+ const char ** pp,
+ debug_type ** slotp,
+ const char * p_end)
{
const char *orig;
int typenums[2];
@@ -1155,6 +1180,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
*slotp = NULL;
orig = *pp;
+ if (orig >= p_end)
+ return DEBUG_TYPE_NULL;
size = -1;
stringp = FALSE;
@@ -1172,7 +1199,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
}
else
{
- if (! parse_stab_type_number (pp, typenums))
+ if (! parse_stab_type_number (pp, typenums, p_end))
return DEBUG_TYPE_NULL;
if (**pp != '=')
@@ -1235,6 +1262,10 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
stringp = TRUE;
break;
+ case 0:
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+
default:
/* Ignore unrecognized type attributes, so future
compilers can invent new ones. */
@@ -1265,6 +1296,10 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
case 'e':
code = DEBUG_KIND_ENUM;
break;
+ case 0:
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+
default:
/* Complain and keep going, so compilers can invent new
cross-reference types. */
@@ -1338,7 +1373,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
hold = *pp;
/* Peek ahead at the number to detect void. */
- if (! parse_stab_type_number (pp, xtypenums))
+ if (! parse_stab_type_number (pp, xtypenums, p_end))
return DEBUG_TYPE_NULL;
if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
@@ -1355,7 +1390,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
This means that we can deal with something like
t(1,2)=(3,4)=... which the Lucid compiler uses. */
dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
+ pp, (debug_type **) NULL, p_end);
if (dtype == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
}
@@ -1374,7 +1409,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
parse_stab_type (dhandle, info,
(const char *) NULL,
pp,
- (debug_type **) NULL));
+ (debug_type **) NULL,
+ p_end));
break;
case '&':
@@ -1382,7 +1418,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
dtype = (debug_make_reference_type
(dhandle,
parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL)));
+ (debug_type **) NULL, p_end)));
break;
case 'f':
@@ -1391,7 +1427,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
dtype = (debug_make_function_type
(dhandle,
parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL),
+ (debug_type **) NULL, p_end),
(debug_type *) NULL, FALSE));
break;
@@ -1402,7 +1438,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
parse_stab_type (dhandle, info,
(const char *) NULL,
pp,
- (debug_type **) NULL));
+ (debug_type **) NULL,
+ p_end));
break;
case 'B':
@@ -1411,7 +1448,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
dtype = (debug_make_volatile_type
(dhandle,
parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL)));
+ (debug_type **) NULL, p_end)));
break;
case '@':
@@ -1424,7 +1461,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
/* Member type. */
domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (domain == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
@@ -1436,7 +1473,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
++*pp;
memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (memtype == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
@@ -1452,7 +1489,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
++*pp;
return_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
+ pp, (debug_type **) NULL, p_end);
if (return_type == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
if (**pp != ';')
@@ -1475,7 +1512,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
bfd_boolean varargs;
domain = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
+ pp, (debug_type **) NULL, p_end);
if (domain == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
@@ -1487,7 +1524,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
++*pp;
return_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
+ pp, (debug_type **) NULL, p_end);
if (return_type == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
@@ -1511,7 +1548,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
}
args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
+ pp, (debug_type **) NULL, p_end);
if (args[n] == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
++n;
@@ -1539,30 +1576,30 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
case 'r':
/* Range type. */
- dtype = parse_stab_range_type (dhandle, info, type_name, pp, typenums);
+ dtype = parse_stab_range_type (dhandle, info, type_name, pp, typenums, p_end);
break;
case 'b':
/* FIXME: gdb checks os9k_stabs here. */
/* Sun ACC builtin int type. */
- dtype = parse_stab_sun_builtin_type (dhandle, pp);
+ dtype = parse_stab_sun_builtin_type (dhandle, pp, p_end);
break;
case 'R':
/* Sun ACC builtin float type. */
- dtype = parse_stab_sun_floating_type (dhandle, pp);
+ dtype = parse_stab_sun_floating_type (dhandle, pp, p_end);
break;
case 'e':
/* Enumeration type. */
- dtype = parse_stab_enum_type (dhandle, pp);
+ dtype = parse_stab_enum_type (dhandle, pp, p_end);
break;
case 's':
case 'u':
/* Struct or union type. */
dtype = parse_stab_struct_type (dhandle, info, type_name, pp,
- descriptor == 's', typenums);
+ descriptor == 's', typenums, p_end);
break;
case 'a':
@@ -1574,7 +1611,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
}
++*pp;
- dtype = parse_stab_array_type (dhandle, info, pp, stringp);
+ dtype = parse_stab_array_type (dhandle, info, pp, stringp, p_end);
break;
case 'S':
@@ -1582,7 +1619,8 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
parse_stab_type (dhandle, info,
(const char *) NULL,
pp,
- (debug_type **) NULL),
+ (debug_type **) NULL,
+ p_end),
stringp);
break;
@@ -1615,7 +1653,7 @@ parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name,
storing them in the vector TYPENUMS. */
static bfd_boolean
-parse_stab_type_number (const char **pp, int *typenums)
+parse_stab_type_number (const char **pp, int *typenums, const char *p_end)
{
const char *orig;
@@ -1624,34 +1662,39 @@ parse_stab_type_number (const char **pp, int *typenums)
if (**pp != '(')
{
typenums[0] = 0;
- typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
+ typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL, p_end);
+ return TRUE;
}
- else
+
+ ++*pp;
+ typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL, p_end);
+ if (**pp != ',')
{
- ++*pp;
- typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ')')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
+ bad_stab (orig);
+ return FALSE;
+ }
+
+ ++*pp;
+ typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL, p_end);
+ if (**pp != ')')
+ {
+ bad_stab (orig);
+ return FALSE;
}
+ ++*pp;
return TRUE;
}
/* Parse a range type. */
static debug_type
-parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type_name, const char **pp, const int *typenums)
+parse_stab_range_type (void * dhandle,
+ struct stab_handle * info,
+ const char * type_name,
+ const char ** pp,
+ const int * typenums,
+ const char * p_end)
{
const char *orig;
int rangenums[2];
@@ -1662,12 +1705,14 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
bfd_boolean ov2, ov3;
orig = *pp;
+ if (orig >= p_end)
+ return DEBUG_TYPE_NULL;
index_type = DEBUG_TYPE_NULL;
/* First comes a type we are a subrange of.
In C it is usually 0, 1 or the type being defined. */
- if (! parse_stab_type_number (pp, rangenums))
+ if (! parse_stab_type_number (pp, rangenums, p_end))
return DEBUG_TYPE_NULL;
self_subrange = (rangenums[0] == typenums[0]
@@ -1677,7 +1722,7 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
{
*pp = orig;
index_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
+ pp, (debug_type **) NULL, p_end);
if (index_type == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;
}
@@ -1688,7 +1733,7 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
/* The remaining two operands are usually lower and upper bounds of
the range. But in some special cases they mean something else. */
s2 = *pp;
- n2 = parse_number (pp, &ov2);
+ n2 = parse_number (pp, &ov2, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -1697,7 +1742,7 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
++*pp;
s3 = *pp;
- n3 = parse_number (pp, &ov3);
+ n3 = parse_number (pp, &ov3, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -1835,13 +1880,15 @@ parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type
FIXME. */
static debug_type
-parse_stab_sun_builtin_type (void *dhandle, const char **pp)
+parse_stab_sun_builtin_type (void *dhandle, const char **pp, const char * p_end)
{
const char *orig;
bfd_boolean unsignedp;
bfd_vma bits;
orig = *pp;
+ if (orig >= p_end)
+ return DEBUG_TYPE_NULL;
switch (**pp)
{
@@ -1870,7 +1917,7 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
by this type, except that unsigned short is 4 instead of 2.
Since this information is redundant with the third number,
we will ignore it. */
- (void) parse_number (pp, (bfd_boolean *) NULL);
+ (void) parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -1879,7 +1926,7 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
++*pp;
/* The second number is always 0, so ignore it too. */
- (void) parse_number (pp, (bfd_boolean *) NULL);
+ (void) parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -1888,7 +1935,7 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
++*pp;
/* The third number is the number of bits for this type. */
- bits = parse_number (pp, (bfd_boolean *) NULL);
+ bits = parse_number (pp, (bfd_boolean *) NULL, p_end);
/* The type *should* end with a semicolon. If it are embedded
in a larger type the semicolon may be the only way to know where
@@ -1908,17 +1955,19 @@ parse_stab_sun_builtin_type (void *dhandle, const char **pp)
/* Parse a builtin floating type generated by the Sun compiler. */
static debug_type
-parse_stab_sun_floating_type (void *dhandle, const char **pp)
+parse_stab_sun_floating_type (void *dhandle, const char **pp, const char *p_end)
{
const char *orig;
bfd_vma details;
bfd_vma bytes;
orig = *pp;
+ if (orig >= p_end)
+ return DEBUG_TYPE_NULL;
/* The first number has more details about the type, for example
FN_COMPLEX. */
- details = parse_number (pp, (bfd_boolean *) NULL);
+ details = parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -1926,7 +1975,7 @@ parse_stab_sun_floating_type (void *dhandle, const char **pp)
}
/* The second number is the number of bytes occupied by this type */
- bytes = parse_number (pp, (bfd_boolean *) NULL);
+ bytes = parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -1944,7 +1993,7 @@ parse_stab_sun_floating_type (void *dhandle, const char **pp)
/* Handle an enum type. */
static debug_type
-parse_stab_enum_type (void *dhandle, const char **pp)
+parse_stab_enum_type (void *dhandle, const char **pp, const char * p_end)
{
const char *orig;
const char **names;
@@ -1953,6 +2002,8 @@ parse_stab_enum_type (void *dhandle, const char **pp)
unsigned int alloc;
orig = *pp;
+ if (orig >= p_end)
+ return DEBUG_TYPE_NULL;
/* FIXME: gdb checks os9k_stabs here. */
@@ -1960,8 +2011,14 @@ parse_stab_enum_type (void *dhandle, const char **pp)
my guess is it's a type of some sort. Just ignore it. */
if (**pp == '-')
{
- while (**pp != ':')
+ while (**pp != ':' && **pp != 0)
++*pp;
+
+ if (**pp == 0)
+ {
+ bad_stab (orig);
+ return DEBUG_TYPE_NULL;
+ }
++*pp;
}
@@ -1993,7 +2050,7 @@ parse_stab_enum_type (void *dhandle, const char **pp)
name = savestring (*pp, p - *pp);
*pp = p + 1;
- val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
+ val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ',')
{
bad_stab (orig);
@@ -2035,9 +2092,13 @@ parse_stab_enum_type (void *dhandle, const char **pp)
*PP will point to "4a:1,0,32;;". */
static debug_type
-parse_stab_struct_type (void *dhandle, struct stab_handle *info,
- const char *tagname, const char **pp,
- bfd_boolean structp, const int *typenums)
+parse_stab_struct_type (void * dhandle,
+ struct stab_handle * info,
+ const char * tagname,
+ const char ** pp,
+ bfd_boolean structp,
+ const int * typenums,
+ const char * p_end)
{
bfd_vma size;
debug_baseclass *baseclasses;
@@ -2048,14 +2109,14 @@ parse_stab_struct_type (void *dhandle, struct stab_handle *info,
bfd_boolean ownvptr;
/* Get the size. */
- size = parse_number (pp, (bfd_boolean *) NULL);
+ size = parse_number (pp, (bfd_boolean *) NULL, p_end);
/* Get the other information. */
- if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
- || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
- || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
+ if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses, p_end)
+ || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics, p_end)
+ || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods, p_end)
|| ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
- &ownvptr))
+ &ownvptr, p_end))
{
if (fields != NULL)
free (fields);
@@ -2098,8 +2159,11 @@ parse_stab_struct_type (void *dhandle, struct stab_handle *info,
Return TRUE for success, FALSE for failure. */
static bfd_boolean
-parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
- const char **pp, debug_baseclass **retp)
+parse_stab_baseclasses (void * dhandle,
+ struct stab_handle * info,
+ const char ** pp,
+ debug_baseclass ** retp,
+ const char * p_end)
{
const char *orig;
unsigned int c, i;
@@ -2108,6 +2172,8 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
*retp = NULL;
orig = *pp;
+ if (orig >= p_end)
+ return FALSE;
if (**pp != '!')
{
@@ -2116,7 +2182,7 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
}
++*pp;
- c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL);
+ c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ',')
{
@@ -2142,6 +2208,9 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
case '1':
is_virtual = TRUE;
break;
+ case 0:
+ bad_stab (orig);
+ return FALSE;
default:
warn_stab (orig, _("unknown virtual character for baseclass"));
is_virtual = FALSE;
@@ -2160,6 +2229,9 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
case '2':
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
+ case 0:
+ bad_stab (orig);
+ return FALSE;
default:
warn_stab (orig, _("unknown visibility character for baseclass"));
visibility = DEBUG_VISIBILITY_PUBLIC;
@@ -2170,7 +2242,7 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
/* The remaining value is the bit offset of the portion of the
object corresponding to this baseclass. Always zero in the
absence of multiple inheritance. */
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
+ bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ',')
{
bad_stab (orig);
@@ -2179,7 +2251,7 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
++*pp;
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (type == DEBUG_TYPE_NULL)
return FALSE;
@@ -2221,9 +2293,12 @@ parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
Returns 1 for success, 0 for failure. */
static bfd_boolean
-parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
- const char **pp, debug_field **retp,
- bfd_boolean *staticsp)
+parse_stab_struct_fields (void * dhandle,
+ struct stab_handle * info,
+ const char ** pp,
+ debug_field ** retp,
+ bfd_boolean * staticsp,
+ const char * p_end)
{
const char *orig;
const char *p;
@@ -2235,6 +2310,8 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
*staticsp = FALSE;
orig = *pp;
+ if (orig >= p_end)
+ return FALSE;
c = 0;
alloc = 10;
@@ -2263,7 +2340,7 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
if ((*p == '$' || *p == '.') && p[1] != '_')
{
++*pp;
- if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
+ if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c, p_end))
{
free (fields);
return FALSE;
@@ -2289,7 +2366,7 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
break;
if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
- staticsp))
+ staticsp, p_end))
return FALSE;
++c;
@@ -2305,8 +2382,11 @@ parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
/* Special GNU C++ name. */
static bfd_boolean
-parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
- const char **pp, debug_field *retp)
+parse_stab_cpp_abbrev (void * dhandle,
+ struct stab_handle * info,
+ const char ** pp,
+ debug_field * retp,
+ const char * p_end)
{
const char *orig;
int cpp_abbrev;
@@ -2319,6 +2399,8 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
*retp = DEBUG_FIELD_NULL;
orig = *pp;
+ if (orig >= p_end)
+ return FALSE;
if (**pp != 'v')
{
@@ -2328,6 +2410,11 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
++*pp;
cpp_abbrev = **pp;
+ if (cpp_abbrev == 0)
+ {
+ bad_stab (orig);
+ return FALSE;
+ }
++*pp;
/* At this point, *pp points to something like "22:23=*22...", where
@@ -2336,7 +2423,7 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
name, and construct the field name. */
context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (context == DEBUG_TYPE_NULL)
return FALSE;
@@ -2370,7 +2457,7 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
++*pp;
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (**pp != ',')
{
bad_stab (orig);
@@ -2378,7 +2465,7 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
}
++*pp;
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
+ bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -2397,9 +2484,13 @@ parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
/* Parse a single field in a struct or union. */
static bfd_boolean
-parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
- const char **pp, const char *p,
- debug_field *retp, bfd_boolean *staticsp)
+parse_stab_one_struct_field (void * dhandle,
+ struct stab_handle * info,
+ const char ** pp,
+ const char * p,
+ debug_field * retp,
+ bfd_boolean * staticsp,
+ const char * p_end)
{
const char *orig;
char *name;
@@ -2409,6 +2500,8 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
bfd_vma bitsize;
orig = *pp;
+ if (orig >= p_end)
+ return FALSE;
/* FIXME: gdb checks ARM_DEMANGLING here. */
@@ -2432,6 +2525,9 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
case '2':
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
+ case 0:
+ bad_stab (orig);
+ return FALSE;
default:
warn_stab (orig, _("unknown visibility character for field"));
visibility = DEBUG_VISIBILITY_PUBLIC;
@@ -2441,7 +2537,7 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
}
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (type == DEBUG_TYPE_NULL)
{
free (name);
@@ -2481,7 +2577,7 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
}
++*pp;
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
+ bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ',')
{
bad_stab (orig);
@@ -2490,7 +2586,7 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
}
++*pp;
- bitsize = parse_number (pp, (bfd_boolean *) NULL);
+ bitsize = parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -2538,9 +2634,13 @@ parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
name (such as `+=') and `.' marks the end of the operator name. */
static bfd_boolean
-parse_stab_members (void *dhandle, struct stab_handle *info,
- const char *tagname, const char **pp,
- const int *typenums, debug_method **retp)
+parse_stab_members (void * dhandle,
+ struct stab_handle * info,
+ const char * tagname,
+ const char ** pp,
+ const int * typenums,
+ debug_method ** retp,
+ const char * p_end)
{
const char *orig;
debug_method *methods;
@@ -2553,6 +2653,8 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
*retp = NULL;
orig = *pp;
+ if (orig >= p_end)
+ return FALSE;
alloc = 0;
methods = NULL;
@@ -2622,7 +2724,7 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
else
{
type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (type == DEBUG_TYPE_NULL)
goto fail;
@@ -2657,6 +2759,9 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
case '1':
visibility = DEBUG_VISIBILITY_PROTECTED;
break;
+ case 0:
+ bad_stab (orig);
+ goto fail;
default:
visibility = DEBUG_VISIBILITY_PUBLIC;
break;
@@ -2705,7 +2810,7 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
bit is supposedly set to distinguish
pointers-to-methods from virtual function indices. */
++*pp;
- voffset = parse_number (pp, (bfd_boolean *) NULL);
+ voffset = parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -2727,7 +2832,8 @@ parse_stab_members (void *dhandle, struct stab_handle *info,
look_ahead_type = parse_stab_type (dhandle, info,
(const char *) NULL,
pp,
- (debug_type **) NULL);
+ (debug_type **) NULL,
+ p_end);
if (**pp == ':')
{
/* g++ version 1 overloaded methods. */
@@ -2986,9 +3092,13 @@ parse_stab_argtypes (void *dhandle, struct stab_handle *info,
so we can look for the vptr base class info. */
static bfd_boolean
-parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
- const char **pp, const int *typenums,
- debug_type *retvptrbase, bfd_boolean *retownvptr)
+parse_stab_tilde_field (void * dhandle,
+ struct stab_handle * info,
+ const char ** pp,
+ const int * typenums,
+ debug_type * retvptrbase,
+ bfd_boolean * retownvptr,
+ const char * p_end)
{
const char *orig;
const char *hold;
@@ -2998,14 +3108,15 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
*retownvptr = FALSE;
orig = *pp;
-
+ if (orig >= p_end)
+ return FALSE;
+
/* If we are positioned at a ';', then skip it. */
if (**pp == ';')
++*pp;
if (**pp != '~')
return TRUE;
-
++*pp;
if (**pp == '=' || **pp == '+' || **pp == '-')
@@ -3017,14 +3128,13 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
if (**pp != '%')
return TRUE;
-
++*pp;
hold = *pp;
/* The next number is the type number of the base class (possibly
our own class) which supplies the vtable for this class. */
- if (! parse_stab_type_number (pp, vtypenums))
+ if (! parse_stab_type_number (pp, vtypenums, p_end))
return FALSE;
if (vtypenums[0] == typenums[0]
@@ -3038,7 +3148,7 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
*pp = hold;
vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
for (p = *pp; *p != ';' && *p != '\0'; p++)
;
if (*p != ';')
@@ -3058,8 +3168,11 @@ parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
/* Read a definition of an array type. */
static debug_type
-parse_stab_array_type (void *dhandle, struct stab_handle *info,
- const char **pp, bfd_boolean stringp)
+parse_stab_array_type (void * dhandle,
+ struct stab_handle * info,
+ const char ** pp,
+ bfd_boolean stringp,
+ const char * p_end)
{
const char *orig;
const char *p;
@@ -3077,13 +3190,16 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
for these, produce a type like float[][]. */
orig = *pp;
+ if (orig >= p_end)
+ return DEBUG_TYPE_NULL;
/* FIXME: gdb checks os9k_stabs here. */
/* If the index type is type 0, we take it as int. */
p = *pp;
- if (! parse_stab_type_number (&p, typenums))
+ if (! parse_stab_type_number (&p, typenums, p_end))
return DEBUG_TYPE_NULL;
+
if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
{
index_type = debug_find_named_type (dhandle, "int");
@@ -3098,7 +3214,7 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
else
{
index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
}
if (**pp != ';')
@@ -3110,13 +3226,13 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
adjustable = FALSE;
- if (! ISDIGIT (**pp) && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '-' && **pp != 0)
{
++*pp;
adjustable = TRUE;
}
- lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
+ lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -3124,13 +3240,13 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
}
++*pp;
- if (! ISDIGIT (**pp) && **pp != '-')
+ if (! ISDIGIT (**pp) && **pp != '-' && **pp != 0)
{
++*pp;
adjustable = TRUE;
}
- upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
+ upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL, p_end);
if (**pp != ';')
{
bad_stab (orig);
@@ -3139,7 +3255,7 @@ parse_stab_array_type (void *dhandle, struct stab_handle *info,
++*pp;
element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
+ (debug_type **) NULL, p_end);
if (element_type == DEBUG_TYPE_NULL)
return DEBUG_TYPE_NULL;