partial revert of b1eaa3021f (#3174)

It is necessary to use a fake NameAndToken in
mTypesUsedInTemplateInstantiation rather than a Token pointer so the
template simplifiers internal state is kept valid when tokens are
deleted. This prevents a use after free.

Co-authored-by: Robert Reif <reif@FX6840>
This commit is contained in:
IOBYTE 2021-03-18 04:15:21 -04:00 committed by GitHub
parent 8fffb84aad
commit b1b7fbb63a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 5 deletions

View File

@ -1650,7 +1650,7 @@ void TemplateSimplifier::expandTemplate(
std::stack<Token *> brackets1; // holds "(" and "{" tokens
bool pointerType = false;
Token * const dst1 = dst->previous();
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype];
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>"));
typetok = typetok->next()) {
if (typeindentlevel == 0 && typetok->str() == "*")
@ -1896,7 +1896,7 @@ void TemplateSimplifier::expandTemplate(
if (itype < typeParametersInDeclaration.size()) {
unsigned int typeindentlevel = 0;
std::stack<Token *> brackets1; // holds "(" and "{" tokens
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype];
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
typetok && (typeindentlevel>0 || !Token::Match(typetok, ",|>"));
typetok = typetok->next()) {
if (!Token::simpleMatch(typetok, "...")) {
@ -2003,7 +2003,7 @@ void TemplateSimplifier::expandTemplate(
std::stack<Token *> brackets1; // holds "(" and "{" tokens
Token * const beforeTypeToken = mTokenList.back();
bool pointerType = false;
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype];
for (const Token *typetok = mTypesUsedInTemplateInstantiation[itype].token();
typetok && (typeindentlevel > 0 || !Token::Match(typetok, ",|>"));
typetok = typetok->next()) {
if (typeindentlevel == 0 && typetok->str() == "*")
@ -2922,7 +2922,7 @@ std::string TemplateSimplifier::getNewName(
else if (indentlevel > 0 && Token::Match(tok3, "> [,>]"))
--indentlevel;
if (indentlevel == 0 && Token::Match(tok3->previous(), "[<,]")) {
mTypesUsedInTemplateInstantiation.push_back(tok3);
mTypesUsedInTemplateInstantiation.emplace_back(tok3, "");
}
if (tok3->str() == "(")
++indentlevel;

View File

@ -501,7 +501,7 @@ private:
std::list<TokenAndName> mInstantiatedTemplates;
std::list<TokenAndName> mMemberFunctionsToDelete;
std::vector<TokenAndName> mExplicitInstantiationsToDelete;
std::vector<const Token *> mTypesUsedInTemplateInstantiation;
std::vector<TokenAndName> mTypesUsedInTemplateInstantiation;
std::unordered_map<const Token*, int> mTemplateNamePos;
};

View File

@ -212,6 +212,7 @@ private:
TEST_CASE(template167);
TEST_CASE(template168);
TEST_CASE(template169);
TEST_CASE(template170); // crash
TEST_CASE(template_specialization_1); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_specialization_2); // #7868 - template specialization template <typename T> struct S<C<T>> {..};
TEST_CASE(template_enum); // #6299 Syntax error in complex enum declaration (including template)
@ -4363,6 +4364,20 @@ private:
ASSERT_EQUALS(exp, tok(code));
}
void template170() { // crash
const char code[] = "template <int b> int a = 0;\n"
"void c() {\n"
" a<1>;\n"
" [](auto b) {};\n"
"}";
const char exp[] = "int a<1> ; a<1> = 0 ; "
"void c ( ) { "
"a<1> ; "
"[ ] ( auto b ) { } ; "
"}";
ASSERT_EQUALS(exp, tok(code));
}
void template_specialization_1() { // #7868 - template specialization template <typename T> struct S<C<T>> {..};
const char code[] = "template <typename T> struct C {};\n"
"template <typename T> struct S {a};\n"