summaryrefslogtreecommitdiff
path: root/src/cxa_demangle.cpp
diff options
context:
space:
mode:
authorHoward Hinnant <hhinnant@apple.com>2012-11-30 18:43:50 +0000
committerHoward Hinnant <hhinnant@apple.com>2012-11-30 18:43:50 +0000
commit342f2f9ffa476d63a1fe1fa718b3243db2c7c5a7 (patch)
tree3c6d36d5f2644a45913abfc31713e5e916a5677a /src/cxa_demangle.cpp
parent06bbbdde3c601994cd92206c6afe26fbc67812ba (diff)
__list::ends_with_template was giving the wrong answer for empty lists. And __parse_unnamed_type_name wasn't properly handling the list of paramters and was not safe against incorrectly mangled lambdas (running past last).
git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@169022 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'src/cxa_demangle.cpp')
-rw-r--r--src/cxa_demangle.cpp81
1 files changed, 51 insertions, 30 deletions
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp
index 32f63eb..366337c 100644
--- a/src/cxa_demangle.cpp
+++ b/src/cxa_demangle.cpp
@@ -133,9 +133,14 @@ void display(__node* x, int indent = 0)
{
for (int i = 0; i < 2*indent; ++i)
printf(" ");
- char* buf = (char*)malloc(x->size());
+ size_t sz = x->size();
+ char* buf = (char*)calloc(sz+10, 1);
x->get_demangled_name(buf);
- printf("%s %s, %p\n", typeid(*x).name(), buf, x);
+ printf("%s [%ld] %s, %p\n", typeid(*x).name(), sz, buf, x);
+ if (strlen(buf) != sz)
+ {
+ printf("strlen(buf) = %ld and size = %ld\n", strlen(buf), sz);
+ }
free(buf);
display(x->__left_, indent+1);
display(x->__right_, indent+1);
@@ -3822,10 +3827,14 @@ public:
}
virtual bool ends_with_template(bool parsing = false) const
{
- if (__right_ != NULL)
+ if (__right_ && __right_->size() > 0)
+ {
return __right_->ends_with_template(parsing);
- if (__left_ != NULL)
+ }
+ else if (__left_ && __left_->size() > 0)
+ {
return __left_->ends_with_template(parsing);
+ }
return false;
}
virtual bool fix_forward_references(__node** t_begin, __node** t_end)
@@ -6969,50 +6978,62 @@ __demangle_tree::__parse_unnamed_type_name(const char* first, const char* last)
{
case 't':
case 'l':
- first += 2;
-
+ {
+ const char* t = first + 2;
+ __node* params = 0;
if (type == 'l')
{
- __root_ = 0;
- if (first[0] == 'v')
+ if (*t == 'v')
{
// void lambda
- ++first;
- if (first[0] == 'E')
- ++first;
+ ++t;
+ if (t != last && *t == 'E')
+ ++t;
else
return first;
}
else
{
- while (first[0] && first[0] != 'E')
+ const char* t1 = __parse_type(t, last);
+ if (t1 == t || !__make<__list>(__root_))
+ return first;
+ params = __root_;
+ __node* prev = params;
+ t = t1;
+ while (true)
{
- const char *old = first;
- first = __parse_type(first, last);
- if (first == old)
+ t1 = __parse_type(t, last);
+ if (t1 == t)
break;
+ if (!__make<__list>(__root_))
+ return first;
+ t = t1;
+ prev->__right_ = __root_;
+ __root_->__size_ = prev->__size_ + 1;
+ prev = __root_;
}
- if (first[0] == 'E')
- ++first;
- else
+ if (t == last || *t != 'E')
return first;
+ ++t;
}
}
- const char *number_start = first;
- first = __parse_number(first, last);
- const char *number_end = first;
- if (first[0] == '_')
- {
- ++first;
- }
- else
+ const char* number_start = t;
+ const char* number_end = __parse_number(t, last);
+ if (number_end == last || *number_end != '_')
return first;
-
+ t = number_end + 1;
if (type == 'l')
- __make<__lambda_node>(__root_, number_start, static_cast<size_t>(number_end - number_start));
+ {
+ if (!__make<__lambda_node>(params, number_start, static_cast<size_t>(number_end - number_start)))
+ return first;
+ }
else
- __make<__unnamed>(number_start, static_cast<size_t>(number_end - number_start));
-
+ {
+ if (!__make<__unnamed>(number_start, static_cast<size_t>(number_end - number_start)))
+ return first;
+ }
+ first = t;
+ }
break;
}
}