Author: epilk Date: Wed May 24 00:44:19 2017 New Revision: 303718 URL: http://llvm.org/viewvc/llvm-project?rev=303718&view=rev Log: [demangler] Fix a crash in the demangler during parsing of a lamdba
The problem is that multiple types could have been parsed from parse_type(), which the lamdba parameter parsing didn't handle. Differential revision: https://reviews.llvm.org/D33368 Modified: libcxxabi/trunk/src/cxa_demangle.cpp libcxxabi/trunk/test/test_demangle.pass.cpp Modified: libcxxabi/trunk/src/cxa_demangle.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp?rev=303718&r1=303717&r2=303718&view=diff ============================================================================== --- libcxxabi/trunk/src/cxa_demangle.cpp (original) +++ libcxxabi/trunk/src/cxa_demangle.cpp Wed May 24 00:44:19 2017 @@ -15,6 +15,7 @@ #include <algorithm> #include <string> #include <numeric> +#include <cassert> #include <cstdlib> #include <cstring> #include <cctype> @@ -3015,6 +3016,7 @@ parse_unnamed_type_name(const char* firs break; case 'l': { + size_t lambda_pos = db.names.size(); db.names.push_back(typename C::String("'lambda'(")); const char* t0 = first+2; if (first[2] == 'v') @@ -3024,36 +3026,41 @@ parse_unnamed_type_name(const char* firs } else { - const char* t1 = parse_type(t0, last, db); - if (t1 == t0) - { - if(!db.names.empty()) - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first.append(tmp); - t0 = t1; + bool is_first_it = true; while (true) { - t1 = parse_type(t0, last, db); + long k0 = static_cast<long>(db.names.size()); + const char* t1 = parse_type(t0, last, db); + long k1 = static_cast<long>(db.names.size()); if (t1 == t0) break; - if (db.names.size() < 2) + assert(k0 <= k1 && "parse_type() mutated the name stack"); + if (k1 == k0) return first; - tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - } + // If the call to parse_type above found a pack expansion + // substitution, then multiple names could have been + // inserted into the name table. Walk through the names, + // appending each onto the lambda's parameter list. + std::for_each(db.names.begin() + k0, db.names.begin() + k1, + [&](typename C::sub_type::value_type &pair) { + if (pair.empty()) + return; + auto &lambda = db.names[lambda_pos].first; + if (!is_first_it) + lambda.append(", "); + is_first_it = false; + lambda.append(pair.move_full()); + }); + db.names.erase(db.names.begin() + k0, db.names.end()); t0 = t1; } - if(db.names.empty()) + if (is_first_it) + { + if (!db.names.empty()) + db.names.pop_back(); + return first; + } + if (db.names.empty() || db.names.size() - 1 != lambda_pos) return first; db.names.back().first.append(")"); } @@ -4964,6 +4971,7 @@ struct string_pair string_pair(const char (&s)[N]) : first(s, N-1) {} size_t size() const {return first.size() + second.size();} + bool empty() const { return first.empty() && second.empty(); } StrT full() const {return first + second;} StrT move_full() {return std::move(first) + std::move(second);} }; Modified: libcxxabi/trunk/test/test_demangle.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/test_demangle.pass.cpp?rev=303718&r1=303717&r2=303718&view=diff ============================================================================== --- libcxxabi/trunk/test/test_demangle.pass.cpp (original) +++ libcxxabi/trunk/test/test_demangle.pass.cpp Wed May 24 00:44:19 2017 @@ -29604,6 +29604,7 @@ const char* cases[][2] = {"PFvRmOE", "void (*)(unsigned long&) &&"}, {"_ZTW1x", "thread-local wrapper routine for x"}, {"_ZTHN3fooE", "thread-local initialization routine for foo"}, + {"_Z4algoIJiiiEEvZ1gEUlT_E_", "void algo<int, int, int>(g::'lambda'(int, int, int))"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); @@ -29664,7 +29665,8 @@ const char* invalid_cases[] = "\x44\x74\x71\x75\x35\x2A\xDF\x74\x44\x61\x73\x63\x35\x2A\x3B\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x63\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x33\x44\x76\x35", "\x44\x74\x70\x74\x71\x75\x32\x43\x41\x38\x65\x6E\x9B\x72\x4D\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x38\xD3\x73\x9E\x2A\x37", "\x46\x44\x74\x70\x74\x71\x75\x32\x43\x41\x72\x4D\x6E\x65\x34\x9F\xC1\x43\x41\x72\x4D\x6E\x77\x38\x9A\x8E\x44\x6F\x64\x6C\x53\xF9\x5F\x70\x74\x70\x69\x45\x34\xD3\x73\x9E\x2A\x37\x72\x33\x8E\x3A\x29\x8E\x44\x35", - "_ZcvCiIJEEDvT__FFFFT_vT_v", + "_ZcvCiIJEEDvT__FFFFT_vT_v", + "Z1JIJ1_T_EE3o00EUlT_E0", }; const unsigned NI = sizeof(invalid_cases) / sizeof(invalid_cases[0]); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits