* 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:
parent
5f9aac7b01
commit
6ef6358e51
@ -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>
|
||||
J"orn Rennecke <joern.rennecke@st.com>
|
||||
|
||||
|
@ -913,9 +913,9 @@ CP_STATIC_IF_GLIBCPP_V3
|
||||
struct demangle_component *
|
||||
cplus_demangle_mangled_name (struct d_info *di, int top_level)
|
||||
{
|
||||
if (d_next_char (di) != '_')
|
||||
if (! d_check_char (di, '_'))
|
||||
return NULL;
|
||||
if (d_next_char (di) != 'Z')
|
||||
if (! d_check_char (di, 'Z'))
|
||||
return NULL;
|
||||
return d_encoding (di, top_level);
|
||||
}
|
||||
@ -1123,7 +1123,7 @@ d_nested_name (struct d_info *di)
|
||||
struct demangle_component *ret;
|
||||
struct demangle_component **pret;
|
||||
|
||||
if (d_next_char (di) != 'N')
|
||||
if (! d_check_char (di, 'N'))
|
||||
return NULL;
|
||||
|
||||
pret = d_cv_qualifiers (di, &ret, 1);
|
||||
@ -1134,7 +1134,7 @@ d_nested_name (struct d_info *di)
|
||||
if (*pret == NULL)
|
||||
return NULL;
|
||||
|
||||
if (d_next_char (di) != 'E')
|
||||
if (! d_check_char (di, 'E'))
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
@ -1449,11 +1449,8 @@ d_operator_name (struct d_info *di)
|
||||
static struct demangle_component *
|
||||
d_special_name (struct d_info *di)
|
||||
{
|
||||
char c;
|
||||
|
||||
di->expansion += 20;
|
||||
c = d_next_char (di);
|
||||
if (c == 'T')
|
||||
if (d_check_char (di, 'T'))
|
||||
{
|
||||
switch (d_next_char (di))
|
||||
{
|
||||
@ -1502,7 +1499,7 @@ d_special_name (struct d_info *di)
|
||||
offset = d_number (di);
|
||||
if (offset < 0)
|
||||
return NULL;
|
||||
if (d_next_char (di) != '_')
|
||||
if (! d_check_char (di, '_'))
|
||||
return NULL;
|
||||
base_type = cplus_demangle_type (di);
|
||||
/* We don't display the offset. FIXME: We should display
|
||||
@ -1523,7 +1520,7 @@ d_special_name (struct d_info *di)
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if (c == 'G')
|
||||
else if (d_check_char (di, 'G'))
|
||||
{
|
||||
switch (d_next_char (di))
|
||||
{
|
||||
@ -1570,14 +1567,14 @@ d_call_offset (struct d_info *di, int c)
|
||||
else if (c == 'v')
|
||||
{
|
||||
d_number (di);
|
||||
if (d_next_char (di) != '_')
|
||||
if (! d_check_char (di, '_'))
|
||||
return 0;
|
||||
d_number (di);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (d_next_char (di) != '_')
|
||||
if (! d_check_char (di, '_'))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -1601,13 +1598,13 @@ d_ctor_dtor_name (struct d_info *di)
|
||||
else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
|
||||
di->expansion += di->last_name->u.s_string.len;
|
||||
}
|
||||
switch (d_next_char (di))
|
||||
switch (d_peek_char (di))
|
||||
{
|
||||
case 'C':
|
||||
{
|
||||
enum gnu_v3_ctor_kinds kind;
|
||||
|
||||
switch (d_next_char (di))
|
||||
switch (d_peek_next_char (di))
|
||||
{
|
||||
case '1':
|
||||
kind = gnu_v3_complete_object_ctor;
|
||||
@ -1621,6 +1618,7 @@ d_ctor_dtor_name (struct d_info *di)
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
d_advance (di, 2);
|
||||
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;
|
||||
|
||||
switch (d_next_char (di))
|
||||
switch (d_peek_next_char (di))
|
||||
{
|
||||
case '0':
|
||||
kind = gnu_v3_deleting_dtor;
|
||||
@ -1642,6 +1640,7 @@ d_ctor_dtor_name (struct d_info *di)
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
d_advance (di, 2);
|
||||
return d_make_dtor (di, kind, di->last_name);
|
||||
}
|
||||
|
||||
@ -1925,7 +1924,7 @@ d_function_type (struct d_info *di)
|
||||
{
|
||||
struct demangle_component *ret;
|
||||
|
||||
if (d_next_char (di) != 'F')
|
||||
if (! d_check_char (di, 'F'))
|
||||
return NULL;
|
||||
if (d_peek_char (di) == 'Y')
|
||||
{
|
||||
@ -1934,7 +1933,7 @@ d_function_type (struct d_info *di)
|
||||
d_advance (di, 1);
|
||||
}
|
||||
ret = d_bare_function_type (di, 1);
|
||||
if (d_next_char (di) != 'E')
|
||||
if (! d_check_char (di, 'E'))
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
@ -2021,7 +2020,7 @@ d_array_type (struct d_info *di)
|
||||
char peek;
|
||||
struct demangle_component *dim;
|
||||
|
||||
if (d_next_char (di) != 'A')
|
||||
if (! d_check_char (di, 'A'))
|
||||
return NULL;
|
||||
|
||||
peek = d_peek_char (di);
|
||||
@ -2049,7 +2048,7 @@ d_array_type (struct d_info *di)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (d_next_char (di) != '_')
|
||||
if (! d_check_char (di, '_'))
|
||||
return NULL;
|
||||
|
||||
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 **pmem;
|
||||
|
||||
if (d_next_char (di) != 'M')
|
||||
if (! d_check_char (di, 'M'))
|
||||
return NULL;
|
||||
|
||||
cl = cplus_demangle_type (di);
|
||||
@ -2109,7 +2108,7 @@ d_template_param (struct d_info *di)
|
||||
{
|
||||
long param;
|
||||
|
||||
if (d_next_char (di) != 'T')
|
||||
if (! d_check_char (di, 'T'))
|
||||
return NULL;
|
||||
|
||||
if (d_peek_char (di) == '_')
|
||||
@ -2122,7 +2121,7 @@ d_template_param (struct d_info *di)
|
||||
param += 1;
|
||||
}
|
||||
|
||||
if (d_next_char (di) != '_')
|
||||
if (! d_check_char (di, '_'))
|
||||
return NULL;
|
||||
|
||||
++di->did_subs;
|
||||
@ -2144,7 +2143,7 @@ d_template_args (struct d_info *di)
|
||||
constructor or destructor. */
|
||||
hold_last_name = di->last_name;
|
||||
|
||||
if (d_next_char (di) != 'I')
|
||||
if (! d_check_char (di, 'I'))
|
||||
return NULL;
|
||||
|
||||
al = NULL;
|
||||
@ -2189,7 +2188,7 @@ d_template_arg (struct d_info *di)
|
||||
case 'X':
|
||||
d_advance (di, 1);
|
||||
ret = d_expression (di);
|
||||
if (d_next_char (di) != 'E')
|
||||
if (! d_check_char (di, 'E'))
|
||||
return NULL;
|
||||
return ret;
|
||||
|
||||
@ -2316,7 +2315,7 @@ d_expr_primary (struct d_info *di)
|
||||
{
|
||||
struct demangle_component *ret;
|
||||
|
||||
if (d_next_char (di) != 'L')
|
||||
if (! d_check_char (di, 'L'))
|
||||
return NULL;
|
||||
if (d_peek_char (di) == '_')
|
||||
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));
|
||||
}
|
||||
if (d_next_char (di) != 'E')
|
||||
if (! d_check_char (di, 'E'))
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
@ -2376,12 +2375,12 @@ d_local_name (struct d_info *di)
|
||||
{
|
||||
struct demangle_component *function;
|
||||
|
||||
if (d_next_char (di) != 'Z')
|
||||
if (! d_check_char (di, 'Z'))
|
||||
return NULL;
|
||||
|
||||
function = d_encoding (di, 0);
|
||||
|
||||
if (d_next_char (di) != 'E')
|
||||
if (! d_check_char (di, 'E'))
|
||||
return NULL;
|
||||
|
||||
if (d_peek_char (di) == 's')
|
||||
@ -2486,7 +2485,7 @@ d_substitution (struct d_info *di, int prefix)
|
||||
{
|
||||
char c;
|
||||
|
||||
if (d_next_char (di) != 'S')
|
||||
if (! d_check_char (di, 'S'))
|
||||
return NULL;
|
||||
|
||||
c = d_next_char (di);
|
||||
|
@ -123,10 +123,16 @@ struct d_info
|
||||
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_next_char(di) ((di)->n[1])
|
||||
#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)
|
||||
|
||||
/* Functions and arrays in cp-demangle.c which are referenced by
|
||||
|
@ -3816,3 +3816,25 @@ f
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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
|
||||
fail (lineno, opts, in, out, exp)
|
||||
int lineno;
|
||||
@ -150,6 +194,8 @@ main(argc, argv)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const char *inp;
|
||||
|
||||
getline (&format);
|
||||
if (feof (stdin))
|
||||
break;
|
||||
@ -157,6 +203,8 @@ main(argc, argv)
|
||||
getline (&input);
|
||||
getline (&expect);
|
||||
|
||||
inp = protect_end (input.data);
|
||||
|
||||
tests++;
|
||||
|
||||
no_params = 0;
|
||||
@ -237,14 +285,14 @@ main(argc, argv)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -259,7 +307,7 @@ main(argc, argv)
|
||||
|
||||
cplus_demangle_set_style (style);
|
||||
|
||||
result = cplus_demangle (input.data,
|
||||
result = cplus_demangle (inp,
|
||||
DMGL_PARAMS|DMGL_ANSI|DMGL_TYPES
|
||||
|(ret_postfix ? DMGL_RET_POSTFIX : 0));
|
||||
|
||||
@ -275,7 +323,7 @@ main(argc, argv)
|
||||
if (no_params)
|
||||
{
|
||||
getline (&expect);
|
||||
result = cplus_demangle (input.data, DMGL_ANSI|DMGL_TYPES);
|
||||
result = cplus_demangle (inp, DMGL_ANSI|DMGL_TYPES);
|
||||
|
||||
if (result
|
||||
? strcmp (result, expect.data)
|
||||
|
Loading…
Reference in New Issue
Block a user