diff options
author | Howard Hinnant <hhinnant@apple.com> | 2013-06-23 17:14:35 +0000 |
---|---|---|
committer | Howard Hinnant <hhinnant@apple.com> | 2013-06-23 17:14:35 +0000 |
commit | eb8d46c54e181eea4d33b96a9a13e2ac0bd329a8 (patch) | |
tree | 8e7459f5d1d79b4dec1bb1199be588fa587d9132 | |
parent | ab8cfb1dfb4bb7e5c8294a81639f08b7ff14ade9 (diff) |
After a private conversation with Arthur O'Dwyer, and a good night's sleep, I believe this fix is a better fix than what I committed in r184656 yesterday. I've basically moved the checking for '`' from the start of the demangling process to the end of it. In the process I discovered that one of the test cases no longer demangled to the expected string. After further investigation I believe this case to not be a valid mangled string, and so I moved the test case to the 'invalid cases'. The reason I believe it is invalid is that it should use T_ instead of T0_ to index the template parameter.
git-svn-id: https://llvm.org/svn/llvm-project/libcxxabi/trunk@184668 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | src/cxa_demangle.cpp | 43 | ||||
-rw-r--r-- | test/test_demangle.cpp | 2 |
2 files changed, 38 insertions, 7 deletions
diff --git a/src/cxa_demangle.cpp b/src/cxa_demangle.cpp index 91d16cd..e49ab44 100644 --- a/src/cxa_demangle.cpp +++ b/src/cxa_demangle.cpp @@ -4382,7 +4382,7 @@ template <class C> void demangle(const char* first, const char* last, C& db, int& status) { - if (first >= last || std::find(first, last, '`') != last) + if (first >= last) { status = invalid_mangled_name; return; @@ -4423,21 +4423,52 @@ demangle(const char* first, const char* last, C& db, int& status) if (t != last) status = invalid_mangled_name; } + if (status == success && db.names.empty()) + status = invalid_mangled_name; if (status == success && db.fix_forward_references) { - db.names.reserve(db.names.size()+1); - auto& nm = db.names.back().first; + auto nm = db.names.back().move_full(); + db.names.pop_back(); size_t p = nm.size(); while (p != 0) { if (nm[--p] == '`') { + size_t k0 = db.names.size(); const char* t = parse_template_param(&nm[p+1], &nm[nm.size()], db); - auto s = db.names.back().move_full(); - db.names.pop_back(); - nm.replace(p, static_cast<std::size_t>(t - &nm[p]), s); + size_t k1 = db.names.size(); + if (t == &nm[p+1]) + { + status = invalid_mangled_name; + return; + } + if (k1 == k0) + { + nm.erase(p, static_cast<std::size_t>(t - &nm[p])); + } + else + { + if (db.names[k0].first.front() == '`') + { + status = invalid_mangled_name; + return; + } + size_t p2 = static_cast<size_t>(t - &nm[p]); + size_t s = db.names[k0].size(); + nm.replace(p, p2, db.names[k0].move_full()); + p2 = p + s; + for (size_t k = k0+1; k < k1; ++k) + { + s = db.names[k].size() + 2; + nm.insert(p2, ", " + db.names[k].move_full()); + p2 += s; + } + for (; k1 > k0; --k1) + db.names.pop_back(); + } } } + db.names.push_back(std::move(nm)); } } diff --git a/test/test_demangle.cpp b/test/test_demangle.cpp index b1019e5..d024d46 100644 --- a/test/test_demangle.cpp +++ b/test/test_demangle.cpp @@ -29575,7 +29575,6 @@ const char* cases[][2] = {"_ZSteqIcEN9__gnu_cxx11__enable_ifIXsr9__is_charIT_EE7__valueEbE6__typeERKSbIS2_St11char_traitsIS2_ESaIS2_EESA_", "__gnu_cxx::__enable_if<__is_char<char>::__value, bool>::__type std::operator==<char>(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)"}, {"_ZZ10+[Foo bar]E3Baz", "+[Foo bar]::Baz"}, {"_ZN9__gnu_cxx17__normal_iteratorIPKSt4pairISsbESt6vectorIS2_SaIS2_EEEC5ERKS4_", "__gnu_cxx::__normal_iterator<std::pair<std::string, bool> const*, std::vector<std::pair<std::string, bool>, std::allocator<std::pair<std::string, bool> > > >::__normal_iterator(std::pair<std::string, bool> const* const&)"}, - {"_ZNSt16allocator_traitsISaIN4llvm3sys2fs18directory_iteratorEEE9constructIS3_IS3_EEEDTcl12_S_constructfp_fp0_spcl7forwardIT0_Efp1_EEERS4_PT_DpOS7_", "decltype(_S_construct(fpfp0forward<`T0_>(fp1))) std::allocator_traits<std::allocator<llvm::sys::fs::directory_iterator> >::construct<llvm::sys::fs::directory_iterator<llvm::sys::fs::directory_iterator> >(std::allocator<llvm::sys::fs::directory_iterator>&, llvm::sys::fs::directory_iterator<llvm::sys::fs::directory_iterator>*, llvm::sys::fs::directory_iterator<llvm::sys::fs::directory_iterator>&&)"}, {"_Z1fIiEDTeqfp_LDnEEPT_", "decltype((fp) == (std::nullptr_t)) f<int>(int*)"}, {"_Z1fIiEDTeqfp1_LDnEEicPT_", "decltype((fp1) == (std::nullptr_t)) f<int>(int, char, int*)"}, {"_ZZN1S1fEiiEd0_NKUlvE_clEv", "S::f(int, int)::'lambda'()::operator()() const"}, @@ -29594,6 +29593,7 @@ const char* invalid_cases[] = "NSoERj5E=Y1[uM:ga", "Aon_PmKVPDk7?fg4XP5smMUL6;<WsI_mgbf23cCgsHbT<l8EE\0uVRkNOoXDrgdA4[8IU>Vl<>IL8ayHpiVDDDXTY;^o9;i", "_ZN8Blizza`d6Memory12voidp_returncvPT_IcEEv", + "_ZNSt16allocator_traitsISaIN4llvm3sys2fs18directory_iteratorEEE9constructIS3_IS3_EEEDTcl12_S_constructfp_fp0_spcl7forwardIT0_Efp1_EEERS4_PT_DpOS7_", }; const unsigned NI = sizeof(invalid_cases) / sizeof(invalid_cases[0]); |