diff -rup binutils.orig/binutils/stabs.c binutils-2.30/binutils/stabs.c --- binutils.orig/binutils/stabs.c 2024-10-29 14:00:27.334403933 +0000 +++ binutils-2.30/binutils/stabs.c 2024-10-29 14:02:25.532712776 +0000 @@ -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_boole *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, /* 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, 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, 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 ++p; if (ISDIGIT (*p) || *p == '(' || *p == '-') type = 'l'; + else if (*p == 0) + { + bad_stab (string); + return FALSE; + } else type = *p++; @@ -787,7 +807,7 @@ parse_stab_string (void *dhandle, struct 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 != ',') @@ -812,7 +832,7 @@ parse_stab_string (void *dhandle, struct 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)) @@ -825,7 +845,7 @@ parse_stab_string (void *dhandle, struct 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)) @@ -839,7 +859,7 @@ parse_stab_string (void *dhandle, struct { ++p; if (parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL) + (debug_type **) NULL, string_end) == DEBUG_TYPE_NULL) return FALSE; } @@ -853,7 +873,7 @@ parse_stab_string (void *dhandle, struct /* 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) @@ -889,7 +909,7 @@ parse_stab_string (void *dhandle, struct 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, @@ -901,7 +921,7 @@ parse_stab_string (void *dhandle, struct /* 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 @@ -909,7 +929,7 @@ parse_stab_string (void *dhandle, struct 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; @@ -939,7 +959,7 @@ parse_stab_string (void *dhandle, struct { ++p; if (parse_stab_type (dhandle, info, (const char *) NULL, &p, - (debug_type **) NULL) + (debug_type **) NULL, string_end) == DEBUG_TYPE_NULL) return FALSE; } @@ -949,7 +969,7 @@ parse_stab_string (void *dhandle, struct 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, @@ -960,7 +980,7 @@ parse_stab_string (void *dhandle, struct 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, @@ -974,7 +994,7 @@ parse_stab_string (void *dhandle, struct 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, @@ -984,7 +1004,7 @@ parse_stab_string (void *dhandle, struct 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) @@ -1017,7 +1037,7 @@ parse_stab_string (void *dhandle, struct ++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) @@ -1068,7 +1088,7 @@ parse_stab_string (void *dhandle, struct 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. */ @@ -1080,7 +1100,7 @@ parse_stab_string (void *dhandle, struct 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, @@ -1091,7 +1111,7 @@ parse_stab_string (void *dhandle, struct 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, @@ -1105,7 +1125,7 @@ parse_stab_string (void *dhandle, struct 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, @@ -1156,7 +1176,12 @@ parse_stab_string (void *dhandle, struct 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]; @@ -1169,6 +1194,8 @@ parse_stab_type (void *dhandle, struct s *slotp = NULL; orig = *pp; + if (orig >= p_end) + return DEBUG_TYPE_NULL; size = -1; stringp = FALSE; @@ -1186,7 +1213,7 @@ parse_stab_type (void *dhandle, struct s } else { - if (! parse_stab_type_number (pp, typenums)) + if (! parse_stab_type_number (pp, typenums, p_end)) return DEBUG_TYPE_NULL; if (**pp != '=') @@ -1249,6 +1276,10 @@ parse_stab_type (void *dhandle, struct s stringp = TRUE; break; + case 0: + bad_stab (orig); + return DEBUG_TYPE_NULL; + default: /* Ignore unrecognized type attributes, so future compilers can invent new ones. */ @@ -1279,6 +1310,10 @@ parse_stab_type (void *dhandle, struct s 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. */ @@ -1352,7 +1387,7 @@ parse_stab_type (void *dhandle, struct s 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]) @@ -1369,7 +1404,7 @@ parse_stab_type (void *dhandle, struct s 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; } @@ -1388,7 +1423,8 @@ parse_stab_type (void *dhandle, struct s parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL)); + (debug_type **) NULL, + p_end)); break; case '&': @@ -1396,7 +1432,7 @@ parse_stab_type (void *dhandle, struct s 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': @@ -1405,7 +1441,7 @@ parse_stab_type (void *dhandle, struct s 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; @@ -1416,7 +1452,8 @@ parse_stab_type (void *dhandle, struct s parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL)); + (debug_type **) NULL, + p_end)); break; case 'B': @@ -1425,7 +1462,7 @@ parse_stab_type (void *dhandle, struct s 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 '@': @@ -1438,7 +1475,7 @@ parse_stab_type (void *dhandle, struct s /* 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; @@ -1450,7 +1487,7 @@ parse_stab_type (void *dhandle, struct s ++*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; @@ -1466,7 +1503,7 @@ parse_stab_type (void *dhandle, struct s ++*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 != ';') @@ -1489,7 +1526,7 @@ parse_stab_type (void *dhandle, struct s 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; @@ -1501,7 +1538,7 @@ parse_stab_type (void *dhandle, struct s ++*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; @@ -1527,7 +1564,7 @@ parse_stab_type (void *dhandle, struct s } 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) /* There is a potential resource leak here, but it is not important. */ /* coverity[leaked_storage: FALSE] */ @@ -1557,30 +1594,30 @@ parse_stab_type (void *dhandle, struct s 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': @@ -1592,7 +1629,7 @@ parse_stab_type (void *dhandle, struct s } ++*pp; - dtype = parse_stab_array_type (dhandle, info, pp, stringp); + dtype = parse_stab_array_type (dhandle, info, pp, stringp, p_end); break; case 'S': @@ -1600,7 +1637,8 @@ parse_stab_type (void *dhandle, struct s parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL), + (debug_type **) NULL, + p_end), stringp); break; @@ -1633,7 +1671,7 @@ parse_stab_type (void *dhandle, struct s 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; @@ -1642,34 +1680,39 @@ parse_stab_type_number (const char **pp, 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]; @@ -1680,12 +1723,14 @@ parse_stab_range_type (void *dhandle, st 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] @@ -1695,7 +1740,7 @@ parse_stab_range_type (void *dhandle, st { *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; } @@ -1706,7 +1751,7 @@ parse_stab_range_type (void *dhandle, st /* 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); @@ -1715,7 +1760,7 @@ parse_stab_range_type (void *dhandle, st ++*pp; s3 = *pp; - n3 = parse_number (pp, &ov3); + n3 = parse_number (pp, &ov3, p_end); if (**pp != ';') { bad_stab (orig); @@ -1853,13 +1898,15 @@ parse_stab_range_type (void *dhandle, st 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) { @@ -1888,7 +1935,7 @@ parse_stab_sun_builtin_type (void *dhand 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); @@ -1897,7 +1944,7 @@ parse_stab_sun_builtin_type (void *dhand ++*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); @@ -1906,7 +1953,7 @@ parse_stab_sun_builtin_type (void *dhand ++*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 @@ -1926,17 +1973,19 @@ parse_stab_sun_builtin_type (void *dhand /* 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); @@ -1944,7 +1993,7 @@ parse_stab_sun_floating_type (void *dhan } /* 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); @@ -1962,7 +2011,7 @@ parse_stab_sun_floating_type (void *dhan /* 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; @@ -1971,6 +2020,8 @@ parse_stab_enum_type (void *dhandle, con unsigned int alloc; orig = *pp; + if (orig >= p_end) + return DEBUG_TYPE_NULL; /* FIXME: gdb checks os9k_stabs here. */ @@ -1978,8 +2029,14 @@ parse_stab_enum_type (void *dhandle, con 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; } @@ -2011,7 +2068,7 @@ parse_stab_enum_type (void *dhandle, con 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); @@ -2053,9 +2110,13 @@ parse_stab_enum_type (void *dhandle, con *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; @@ -2066,14 +2127,14 @@ parse_stab_struct_type (void *dhandle, s 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); @@ -2116,8 +2177,11 @@ parse_stab_struct_type (void *dhandle, s 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; @@ -2126,6 +2190,8 @@ parse_stab_baseclasses (void *dhandle, s *retp = NULL; orig = *pp; + if (orig >= p_end) + return FALSE; if (**pp != '!') { @@ -2134,7 +2200,7 @@ parse_stab_baseclasses (void *dhandle, s } ++*pp; - c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL); + c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL, p_end); if (**pp != ',') { @@ -2160,6 +2226,9 @@ parse_stab_baseclasses (void *dhandle, s 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; @@ -2178,6 +2247,9 @@ parse_stab_baseclasses (void *dhandle, s 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; @@ -2188,7 +2260,7 @@ parse_stab_baseclasses (void *dhandle, s /* 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); @@ -2197,7 +2269,7 @@ parse_stab_baseclasses (void *dhandle, s ++*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; @@ -2239,9 +2311,12 @@ parse_stab_baseclasses (void *dhandle, s 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; @@ -2253,6 +2328,8 @@ parse_stab_struct_fields (void *dhandle, *staticsp = FALSE; orig = *pp; + if (orig >= p_end) + return FALSE; c = 0; alloc = 10; @@ -2281,7 +2358,7 @@ parse_stab_struct_fields (void *dhandle, 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; @@ -2307,7 +2384,7 @@ parse_stab_struct_fields (void *dhandle, break; if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c, - staticsp)) + staticsp, p_end)) /* There is a potential resource leak here, but it is not important. */ /* coverity[leaked_storage: FALSE] */ return FALSE; @@ -2325,8 +2402,11 @@ parse_stab_struct_fields (void *dhandle, /* 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; @@ -2339,6 +2419,8 @@ parse_stab_cpp_abbrev (void *dhandle, st *retp = DEBUG_FIELD_NULL; orig = *pp; + if (orig >= p_end) + return FALSE; if (**pp != 'v') { @@ -2348,6 +2430,11 @@ parse_stab_cpp_abbrev (void *dhandle, st ++*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 @@ -2356,7 +2443,7 @@ parse_stab_cpp_abbrev (void *dhandle, st 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; @@ -2392,7 +2479,7 @@ parse_stab_cpp_abbrev (void *dhandle, st ++*pp; type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); + (debug_type **) NULL, p_end); if (**pp != ',') { bad_stab (orig); @@ -2402,7 +2489,7 @@ parse_stab_cpp_abbrev (void *dhandle, st } ++*pp; - bitpos = parse_number (pp, (bfd_boolean *) NULL); + bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end); if (**pp != ';') { bad_stab (orig); @@ -2423,9 +2510,13 @@ parse_stab_cpp_abbrev (void *dhandle, st /* 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; @@ -2435,6 +2526,8 @@ parse_stab_one_struct_field (void *dhand bfd_vma bitsize; orig = *pp; + if (orig >= p_end) + return FALSE; /* FIXME: gdb checks ARM_DEMANGLING here. */ @@ -2458,6 +2551,9 @@ parse_stab_one_struct_field (void *dhand 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; @@ -2467,7 +2563,7 @@ parse_stab_one_struct_field (void *dhand } 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); @@ -2507,7 +2603,7 @@ parse_stab_one_struct_field (void *dhand } ++*pp; - bitpos = parse_number (pp, (bfd_boolean *) NULL); + bitpos = parse_number (pp, (bfd_boolean *) NULL, p_end); if (**pp != ',') { bad_stab (orig); @@ -2516,7 +2612,7 @@ parse_stab_one_struct_field (void *dhand } ++*pp; - bitsize = parse_number (pp, (bfd_boolean *) NULL); + bitsize = parse_number (pp, (bfd_boolean *) NULL, p_end); if (**pp != ';') { bad_stab (orig); @@ -2564,9 +2660,13 @@ parse_stab_one_struct_field (void *dhand 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; @@ -2579,6 +2679,8 @@ parse_stab_members (void *dhandle, struc *retp = NULL; orig = *pp; + if (orig >= p_end) + return FALSE; alloc = 0; methods = NULL; @@ -2648,7 +2750,7 @@ parse_stab_members (void *dhandle, struc 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; @@ -2683,6 +2785,9 @@ parse_stab_members (void *dhandle, struc case '1': visibility = DEBUG_VISIBILITY_PROTECTED; break; + case 0: + bad_stab (orig); + goto fail; default: visibility = DEBUG_VISIBILITY_PUBLIC; break; @@ -2731,7 +2836,7 @@ parse_stab_members (void *dhandle, struc 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); @@ -2753,7 +2858,8 @@ parse_stab_members (void *dhandle, struc 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. */ @@ -3014,9 +3120,13 @@ parse_stab_argtypes (void *dhandle, stru 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; @@ -3026,14 +3136,15 @@ parse_stab_tilde_field (void *dhandle, s *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 == '-') @@ -3045,14 +3156,13 @@ parse_stab_tilde_field (void *dhandle, s 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] @@ -3066,7 +3176,7 @@ parse_stab_tilde_field (void *dhandle, s *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 != ';') @@ -3086,8 +3196,11 @@ parse_stab_tilde_field (void *dhandle, s /* 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; @@ -3105,13 +3218,16 @@ parse_stab_array_type (void *dhandle, st 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"); @@ -3126,7 +3242,7 @@ parse_stab_array_type (void *dhandle, st else { index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp, - (debug_type **) NULL); + (debug_type **) NULL, p_end); } if (**pp != ';') @@ -3140,13 +3256,13 @@ parse_stab_array_type (void *dhandle, st 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); @@ -3156,13 +3272,13 @@ parse_stab_array_type (void *dhandle, st } ++*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); @@ -3173,7 +3289,7 @@ parse_stab_array_type (void *dhandle, st ++*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) /* There is a potential resource leak here, but it is not important. */ /* coverity[leaked_storage: FALSE] */ Only in binutils-2.30/binutils: stabs.c.orig Only in binutils-2.30/binutils: stabs.c.rej