Thanks Mike. I have revised the patch and removed the limits. While perhaps less security critical, without the limits on the loop count (r) the test cases will still consume all your memory and effectively freeze GDB.
* Before any realloc, check for overflow. * string_need now returns 1 if the allocation was successful. * all clients of string_need refrain from extending the string anything if string_need was unsuccessful. > better use unsigned values that are large enough to never overflow. Throughout cplus-dem.c, the length of a string is measured as pointer difference. So, technically length is of type ptrdiff_t which is signed. — a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -55,6 +55,7 @@ void * malloc (); void * realloc (); #endif +#include <limits.h> #include <demangle.h> #undef CURRENT_DEMANGLING_STYLE @@ -379,7 +380,7 @@ static int arm_special (const char **, string *); -static void string_need (string *, int); +static int string_need (string *, int); static void string_delete (string *); @@ -4254,7 +4255,9 @@ } else { - work -> typevec_size *= 2; + if (work -> typevec_size > INT_MAX / 2) + return; + work -> typevec_size *= 2; work -> typevec = XRESIZEVEC (char *, work->typevec, work->typevec_size); } @@ -4281,7 +4284,9 @@ } else { - work -> ksize *= 2; + if (work -> ksize > INT_MAX / 2) + return; + work -> ksize *= 2; work -> ktypevec = XRESIZEVEC (char *, work->ktypevec, work->ksize); } @@ -4294,7 +4299,8 @@ /* Register a B code, and get an index for it. B codes are registered as they are seen, rather than as they are completed, so map<temp<char> > - registers map<temp<char> > as B0, and temp<char> as B1 */ + registers map<temp<char> > as B0, and temp<char> as B1. Returns -1 + if registration was unsuccessful. */ static int register_Btype (struct work_stuff *work) @@ -4310,7 +4316,9 @@ } else { - work -> bsize *= 2; + if (work -> bsize > INT_MAX / 2) + return -1; + work -> bsize *= 2; work -> btypevec = XRESIZEVEC (char *, work->btypevec, work->bsize); } @@ -4328,6 +4336,8 @@ { char *tem; + if (index < 0) + return; tem = XNEWVEC (char, len + 1); memcpy (tem, start, len); tem[len] = '\0'; @@ -4591,7 +4601,8 @@ const char *tem; string_appendn (declp, (*mangled), scan - (*mangled)); - string_need (declp, 1); + if (! string_need (declp, 1)) + return 0; *(declp -> p) = '\0'; /* Consume the function name, including the "__" separating the name @@ -4747,7 +4758,7 @@ /* a mini string-handling package */ -static void +static int string_need (string *s, int n) { int tem; @@ -4765,11 +4776,14 @@ { tem = s->p - s->b; n += tem; + if ( n > INT_MAX / 2) + return 0; n *= 2; s->b = XRESIZEVEC (char, s->b, n); s->p = s->b + tem; s->e = s->b + n; } + return 1; } static void @@ -4811,7 +4825,8 @@ if (s == NULL || *s == '\0') return; n = strlen (s); - string_need (p, n); + if (! string_need (p, n)) + return; memcpy (p->p, s, n); p->p += n; } @@ -4824,7 +4839,8 @@ if (s->b != s->p) { n = s->p - s->b; - string_need (p, n); + if (! string_need (p, n)) + return; memcpy (p->p, s->b, n); p->p += n; } @@ -4835,7 +4851,8 @@ { if (n != 0) { - string_need (p, n); + if (! string_need (p, n)) + return; memcpy (p->p, s, n); p->p += n; } @@ -4866,7 +4883,8 @@ if (n != 0) { - string_need (p, n); + if (! string_need (p, n)) + return; for (q = p->p - 1; q >= p->b; q--) { q[n] = q[0];