mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-24 20:28:28 +08:00
* cp-demangle.h: Add comment explaining what to do to avoid
overrunning string. (d_check_char): New. (d_next_char): Don't advance past trailing '\0'. * cp-demangle.c (cplus_demangle_mangled_name): Use d_check_char. (d_nested_name): Likewise. (d_special_name): Likewise. (d_call_offset): Likewise. (d_function_type): Likewise. (d_array_type): Likewise. (d_pointer_to_member_type): Likewise. (d_template_param): Likewise. (d_template_args): Likewise. (d_template_arg): Likewise. (d_expr_primary): Likewise. (d_local_name): Likewise. (d_substitution): Likewise. (d_ctor_dtor_name): Use d_advance rather than d_next_char. * testsuite/test-demangle.c: Include sys/mman.h. (MAP_ANONYMOUS): Define. (protect_end): New. (main): Use protect_end. * testsuite/demangle-expected: Add testcases for overrunning the end of the string.
This commit is contained in:
@ -1,3 +1,30 @@
|
|||||||
|
2006-12-20 Geoffrey Keating <geoffk@apple.com>
|
||||||
|
|
||||||
|
* cp-demangle.h: Add comment explaining what to do to avoid
|
||||||
|
overrunning string.
|
||||||
|
(d_check_char): New.
|
||||||
|
(d_next_char): Don't advance past trailing '\0'.
|
||||||
|
* cp-demangle.c (cplus_demangle_mangled_name): Use d_check_char.
|
||||||
|
(d_nested_name): Likewise.
|
||||||
|
(d_special_name): Likewise.
|
||||||
|
(d_call_offset): Likewise.
|
||||||
|
(d_function_type): Likewise.
|
||||||
|
(d_array_type): Likewise.
|
||||||
|
(d_pointer_to_member_type): Likewise.
|
||||||
|
(d_template_param): Likewise.
|
||||||
|
(d_template_args): Likewise.
|
||||||
|
(d_template_arg): Likewise.
|
||||||
|
(d_expr_primary): Likewise.
|
||||||
|
(d_local_name): Likewise.
|
||||||
|
(d_substitution): Likewise.
|
||||||
|
(d_ctor_dtor_name): Use d_advance rather than d_next_char.
|
||||||
|
* testsuite/test-demangle.c: Include sys/mman.h.
|
||||||
|
(MAP_ANONYMOUS): Define.
|
||||||
|
(protect_end): New.
|
||||||
|
(main): Use protect_end.
|
||||||
|
* testsuite/demangle-expected: Add testcases for overrunning
|
||||||
|
the end of the string.
|
||||||
|
|
||||||
2006-11-30 Andrew Stubbs <andrew.stubbs@st.com>
|
2006-11-30 Andrew Stubbs <andrew.stubbs@st.com>
|
||||||
J"orn Rennecke <joern.rennecke@st.com>
|
J"orn Rennecke <joern.rennecke@st.com>
|
||||||
|
|
||||||
|
@ -913,9 +913,9 @@ CP_STATIC_IF_GLIBCPP_V3
|
|||||||
struct demangle_component *
|
struct demangle_component *
|
||||||
cplus_demangle_mangled_name (struct d_info *di, int top_level)
|
cplus_demangle_mangled_name (struct d_info *di, int top_level)
|
||||||
{
|
{
|
||||||
if (d_next_char (di) != '_')
|
if (! d_check_char (di, '_'))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (d_next_char (di) != 'Z')
|
if (! d_check_char (di, 'Z'))
|
||||||
return NULL;
|
return NULL;
|
||||||
return d_encoding (di, top_level);
|
return d_encoding (di, top_level);
|
||||||
}
|
}
|
||||||
@ -1123,7 +1123,7 @@ d_nested_name (struct d_info *di)
|
|||||||
struct demangle_component *ret;
|
struct demangle_component *ret;
|
||||||
struct demangle_component **pret;
|
struct demangle_component **pret;
|
||||||
|
|
||||||
if (d_next_char (di) != 'N')
|
if (! d_check_char (di, 'N'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pret = d_cv_qualifiers (di, &ret, 1);
|
pret = d_cv_qualifiers (di, &ret, 1);
|
||||||
@ -1134,7 +1134,7 @@ d_nested_name (struct d_info *di)
|
|||||||
if (*pret == NULL)
|
if (*pret == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (d_next_char (di) != 'E')
|
if (! d_check_char (di, 'E'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -1449,11 +1449,8 @@ d_operator_name (struct d_info *di)
|
|||||||
static struct demangle_component *
|
static struct demangle_component *
|
||||||
d_special_name (struct d_info *di)
|
d_special_name (struct d_info *di)
|
||||||
{
|
{
|
||||||
char c;
|
|
||||||
|
|
||||||
di->expansion += 20;
|
di->expansion += 20;
|
||||||
c = d_next_char (di);
|
if (d_check_char (di, 'T'))
|
||||||
if (c == 'T')
|
|
||||||
{
|
{
|
||||||
switch (d_next_char (di))
|
switch (d_next_char (di))
|
||||||
{
|
{
|
||||||
@ -1502,7 +1499,7 @@ d_special_name (struct d_info *di)
|
|||||||
offset = d_number (di);
|
offset = d_number (di);
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (d_next_char (di) != '_')
|
if (! d_check_char (di, '_'))
|
||||||
return NULL;
|
return NULL;
|
||||||
base_type = cplus_demangle_type (di);
|
base_type = cplus_demangle_type (di);
|
||||||
/* We don't display the offset. FIXME: We should display
|
/* We don't display the offset. FIXME: We should display
|
||||||
@ -1523,7 +1520,7 @@ d_special_name (struct d_info *di)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (c == 'G')
|
else if (d_check_char (di, 'G'))
|
||||||
{
|
{
|
||||||
switch (d_next_char (di))
|
switch (d_next_char (di))
|
||||||
{
|
{
|
||||||
@ -1570,14 +1567,14 @@ d_call_offset (struct d_info *di, int c)
|
|||||||
else if (c == 'v')
|
else if (c == 'v')
|
||||||
{
|
{
|
||||||
d_number (di);
|
d_number (di);
|
||||||
if (d_next_char (di) != '_')
|
if (! d_check_char (di, '_'))
|
||||||
return 0;
|
return 0;
|
||||||
d_number (di);
|
d_number (di);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (d_next_char (di) != '_')
|
if (! d_check_char (di, '_'))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -1601,13 +1598,13 @@ d_ctor_dtor_name (struct d_info *di)
|
|||||||
else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
|
else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
|
||||||
di->expansion += di->last_name->u.s_string.len;
|
di->expansion += di->last_name->u.s_string.len;
|
||||||
}
|
}
|
||||||
switch (d_next_char (di))
|
switch (d_peek_char (di))
|
||||||
{
|
{
|
||||||
case 'C':
|
case 'C':
|
||||||
{
|
{
|
||||||
enum gnu_v3_ctor_kinds kind;
|
enum gnu_v3_ctor_kinds kind;
|
||||||
|
|
||||||
switch (d_next_char (di))
|
switch (d_peek_next_char (di))
|
||||||
{
|
{
|
||||||
case '1':
|
case '1':
|
||||||
kind = gnu_v3_complete_object_ctor;
|
kind = gnu_v3_complete_object_ctor;
|
||||||
@ -1621,6 +1618,7 @@ d_ctor_dtor_name (struct d_info *di)
|
|||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
d_advance (di, 2);
|
||||||
return d_make_ctor (di, kind, di->last_name);
|
return d_make_ctor (di, kind, di->last_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1628,7 +1626,7 @@ d_ctor_dtor_name (struct d_info *di)
|
|||||||
{
|
{
|
||||||
enum gnu_v3_dtor_kinds kind;
|
enum gnu_v3_dtor_kinds kind;
|
||||||
|
|
||||||
switch (d_next_char (di))
|
switch (d_peek_next_char (di))
|
||||||
{
|
{
|
||||||
case '0':
|
case '0':
|
||||||
kind = gnu_v3_deleting_dtor;
|
kind = gnu_v3_deleting_dtor;
|
||||||
@ -1642,6 +1640,7 @@ d_ctor_dtor_name (struct d_info *di)
|
|||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
d_advance (di, 2);
|
||||||
return d_make_dtor (di, kind, di->last_name);
|
return d_make_dtor (di, kind, di->last_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1925,7 +1924,7 @@ d_function_type (struct d_info *di)
|
|||||||
{
|
{
|
||||||
struct demangle_component *ret;
|
struct demangle_component *ret;
|
||||||
|
|
||||||
if (d_next_char (di) != 'F')
|
if (! d_check_char (di, 'F'))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (d_peek_char (di) == 'Y')
|
if (d_peek_char (di) == 'Y')
|
||||||
{
|
{
|
||||||
@ -1934,7 +1933,7 @@ d_function_type (struct d_info *di)
|
|||||||
d_advance (di, 1);
|
d_advance (di, 1);
|
||||||
}
|
}
|
||||||
ret = d_bare_function_type (di, 1);
|
ret = d_bare_function_type (di, 1);
|
||||||
if (d_next_char (di) != 'E')
|
if (! d_check_char (di, 'E'))
|
||||||
return NULL;
|
return NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2021,7 +2020,7 @@ d_array_type (struct d_info *di)
|
|||||||
char peek;
|
char peek;
|
||||||
struct demangle_component *dim;
|
struct demangle_component *dim;
|
||||||
|
|
||||||
if (d_next_char (di) != 'A')
|
if (! d_check_char (di, 'A'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
peek = d_peek_char (di);
|
peek = d_peek_char (di);
|
||||||
@ -2049,7 +2048,7 @@ d_array_type (struct d_info *di)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d_next_char (di) != '_')
|
if (! d_check_char (di, '_'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
|
return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
|
||||||
@ -2065,7 +2064,7 @@ d_pointer_to_member_type (struct d_info *di)
|
|||||||
struct demangle_component *mem;
|
struct demangle_component *mem;
|
||||||
struct demangle_component **pmem;
|
struct demangle_component **pmem;
|
||||||
|
|
||||||
if (d_next_char (di) != 'M')
|
if (! d_check_char (di, 'M'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
cl = cplus_demangle_type (di);
|
cl = cplus_demangle_type (di);
|
||||||
@ -2109,7 +2108,7 @@ d_template_param (struct d_info *di)
|
|||||||
{
|
{
|
||||||
long param;
|
long param;
|
||||||
|
|
||||||
if (d_next_char (di) != 'T')
|
if (! d_check_char (di, 'T'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (d_peek_char (di) == '_')
|
if (d_peek_char (di) == '_')
|
||||||
@ -2122,7 +2121,7 @@ d_template_param (struct d_info *di)
|
|||||||
param += 1;
|
param += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d_next_char (di) != '_')
|
if (! d_check_char (di, '_'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
++di->did_subs;
|
++di->did_subs;
|
||||||
@ -2144,7 +2143,7 @@ d_template_args (struct d_info *di)
|
|||||||
constructor or destructor. */
|
constructor or destructor. */
|
||||||
hold_last_name = di->last_name;
|
hold_last_name = di->last_name;
|
||||||
|
|
||||||
if (d_next_char (di) != 'I')
|
if (! d_check_char (di, 'I'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
al = NULL;
|
al = NULL;
|
||||||
@ -2189,7 +2188,7 @@ d_template_arg (struct d_info *di)
|
|||||||
case 'X':
|
case 'X':
|
||||||
d_advance (di, 1);
|
d_advance (di, 1);
|
||||||
ret = d_expression (di);
|
ret = d_expression (di);
|
||||||
if (d_next_char (di) != 'E')
|
if (! d_check_char (di, 'E'))
|
||||||
return NULL;
|
return NULL;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -2316,7 +2315,7 @@ d_expr_primary (struct d_info *di)
|
|||||||
{
|
{
|
||||||
struct demangle_component *ret;
|
struct demangle_component *ret;
|
||||||
|
|
||||||
if (d_next_char (di) != 'L')
|
if (! d_check_char (di, 'L'))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (d_peek_char (di) == '_')
|
if (d_peek_char (di) == '_')
|
||||||
ret = cplus_demangle_mangled_name (di, 0);
|
ret = cplus_demangle_mangled_name (di, 0);
|
||||||
@ -2362,7 +2361,7 @@ d_expr_primary (struct d_info *di)
|
|||||||
}
|
}
|
||||||
ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
|
ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
|
||||||
}
|
}
|
||||||
if (d_next_char (di) != 'E')
|
if (! d_check_char (di, 'E'))
|
||||||
return NULL;
|
return NULL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -2376,12 +2375,12 @@ d_local_name (struct d_info *di)
|
|||||||
{
|
{
|
||||||
struct demangle_component *function;
|
struct demangle_component *function;
|
||||||
|
|
||||||
if (d_next_char (di) != 'Z')
|
if (! d_check_char (di, 'Z'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
function = d_encoding (di, 0);
|
function = d_encoding (di, 0);
|
||||||
|
|
||||||
if (d_next_char (di) != 'E')
|
if (! d_check_char (di, 'E'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (d_peek_char (di) == 's')
|
if (d_peek_char (di) == 's')
|
||||||
@ -2486,7 +2485,7 @@ d_substitution (struct d_info *di, int prefix)
|
|||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
if (d_next_char (di) != 'S')
|
if (! d_check_char (di, 'S'))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
c = d_next_char (di);
|
c = d_next_char (di);
|
||||||
|
@ -123,10 +123,16 @@ struct d_info
|
|||||||
int expansion;
|
int expansion;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* To avoid running past the ending '\0', don't:
|
||||||
|
- call d_peek_next_char if d_peek_char returned '\0'
|
||||||
|
- call d_advance with an 'i' that is too large
|
||||||
|
- call d_check_char(di, '\0')
|
||||||
|
Everything else is safe. */
|
||||||
#define d_peek_char(di) (*((di)->n))
|
#define d_peek_char(di) (*((di)->n))
|
||||||
#define d_peek_next_char(di) ((di)->n[1])
|
#define d_peek_next_char(di) ((di)->n[1])
|
||||||
#define d_advance(di, i) ((di)->n += (i))
|
#define d_advance(di, i) ((di)->n += (i))
|
||||||
#define d_next_char(di) (*((di)->n++))
|
#define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0)
|
||||||
|
#define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++))
|
||||||
#define d_str(di) ((di)->n)
|
#define d_str(di) ((di)->n)
|
||||||
|
|
||||||
/* Functions and arrays in cp-demangle.c which are referenced by
|
/* Functions and arrays in cp-demangle.c which are referenced by
|
||||||
|
@ -3816,3 +3816,25 @@ f
|
|||||||
SASDASDFASDF_sdfsdf
|
SASDASDFASDF_sdfsdf
|
||||||
SASDASDFASDF_sdfsdf
|
SASDASDFASDF_sdfsdf
|
||||||
SASDASDFASDF_sdfsdf
|
SASDASDFASDF_sdfsdf
|
||||||
|
# These are all cases of invalid manglings where the demangler would read
|
||||||
|
# past the end of the string.
|
||||||
|
# d_name wasn't honouring a NULL from d_substitution
|
||||||
|
--format=gnu-v3
|
||||||
|
_ZSA
|
||||||
|
_ZSA
|
||||||
|
# d_expr_primary wasn't honouring NULL from cplus_demangle_mangled_name
|
||||||
|
--format=gnu-v3
|
||||||
|
_ZN1fIL_
|
||||||
|
_ZN1fIL_
|
||||||
|
# d_operator_name was taking two characters in a row
|
||||||
|
--format=gnu-v3
|
||||||
|
_Za
|
||||||
|
_Za
|
||||||
|
# d_prefix wasn't honouring NULL from d_substitution
|
||||||
|
--format=gnu-v3
|
||||||
|
_ZNSA
|
||||||
|
_ZNSA
|
||||||
|
# d_prefix wasn't honouring NULL from d_template_param
|
||||||
|
--format=gnu-v3
|
||||||
|
_ZNT
|
||||||
|
_ZNT
|
||||||
|
@ -86,6 +86,50 @@ getline(buf)
|
|||||||
buf->alloced = alloc;
|
buf->alloced = alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If we have mmap() and mprotect(), copy the string S just before a
|
||||||
|
protected page, so that if the demangler runs over the end of the
|
||||||
|
string we'll get a fault, and return the address of the new string.
|
||||||
|
If no mmap, or it fails, or it looks too hard, just return S. */
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif
|
||||||
|
#if defined(MAP_ANON) && ! defined (MAP_ANONYMOUS)
|
||||||
|
#define MAP_ANONYMOUS MAP_ANON
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
protect_end (const char * s)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_MMAP) && defined (MAP_ANONYMOUS)
|
||||||
|
size_t pagesize = getpagesize();
|
||||||
|
static char * buf;
|
||||||
|
size_t s_len = strlen (s);
|
||||||
|
char * result;
|
||||||
|
|
||||||
|
/* Don't try if S is too long. */
|
||||||
|
if (s_len >= pagesize)
|
||||||
|
return s;
|
||||||
|
|
||||||
|
/* Allocate one page of allocated space followed by an unmapped
|
||||||
|
page. */
|
||||||
|
if (buf == NULL)
|
||||||
|
{
|
||||||
|
buf = mmap (NULL, pagesize * 2, PROT_READ | PROT_WRITE,
|
||||||
|
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||||
|
if (! buf)
|
||||||
|
return s;
|
||||||
|
munmap (buf + pagesize, pagesize);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = buf + (pagesize - s_len - 1);
|
||||||
|
memcpy (result, s, s_len + 1);
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return s;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fail (lineno, opts, in, out, exp)
|
fail (lineno, opts, in, out, exp)
|
||||||
int lineno;
|
int lineno;
|
||||||
@ -150,6 +194,8 @@ main(argc, argv)
|
|||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
const char *inp;
|
||||||
|
|
||||||
getline (&format);
|
getline (&format);
|
||||||
if (feof (stdin))
|
if (feof (stdin))
|
||||||
break;
|
break;
|
||||||
@ -157,6 +203,8 @@ main(argc, argv)
|
|||||||
getline (&input);
|
getline (&input);
|
||||||
getline (&expect);
|
getline (&expect);
|
||||||
|
|
||||||
|
inp = protect_end (input.data);
|
||||||
|
|
||||||
tests++;
|
tests++;
|
||||||
|
|
||||||
no_params = 0;
|
no_params = 0;
|
||||||
@ -237,14 +285,14 @@ main(argc, argv)
|
|||||||
{
|
{
|
||||||
enum gnu_v3_ctor_kinds kc;
|
enum gnu_v3_ctor_kinds kc;
|
||||||
|
|
||||||
kc = is_gnu_v3_mangled_ctor (input.data);
|
kc = is_gnu_v3_mangled_ctor (inp);
|
||||||
sprintf (buf, "%d", (int) kc);
|
sprintf (buf, "%d", (int) kc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enum gnu_v3_dtor_kinds kd;
|
enum gnu_v3_dtor_kinds kd;
|
||||||
|
|
||||||
kd = is_gnu_v3_mangled_dtor (input.data);
|
kd = is_gnu_v3_mangled_dtor (inp);
|
||||||
sprintf (buf, "%d", (int) kd);
|
sprintf (buf, "%d", (int) kd);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +307,7 @@ main(argc, argv)
|
|||||||
|
|
||||||
cplus_demangle_set_style (style);
|
cplus_demangle_set_style (style);
|
||||||
|
|
||||||
result = cplus_demangle (input.data,
|
result = cplus_demangle (inp,
|
||||||
DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES
|
DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES
|
||||||
|(ret_postfix ? DMGL_RET_POSTFIX : 0));
|
|(ret_postfix ? DMGL_RET_POSTFIX : 0));
|
||||||
|
|
||||||
@ -275,7 +323,7 @@ main(argc, argv)
|
|||||||
if (no_params)
|
if (no_params)
|
||||||
{
|
{
|
||||||
getline (&expect);
|
getline (&expect);
|
||||||
result = cplus_demangle (input.data, DMGL_ANSI|DMGL_TYPES);
|
result = cplus_demangle (inp, DMGL_ANSI|DMGL_TYPES);
|
||||||
|
|
||||||
if (result
|
if (result
|
||||||
? strcmp (result, expect.data)
|
? strcmp (result, expect.data)
|
||||||
|
Reference in New Issue
Block a user