From 04c57381ea15f05a343caba31929c432ecb7df4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Fri, 5 Jan 2018 16:10:13 +0100 Subject: [PATCH] Fixed #8315 (heap use after free: templatesimplifier) --- lib/templatesimplifier.cpp | 57 +++++++++++++++++++++-------------- test/testsimplifytemplate.cpp | 9 ++++++ 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/lib/templatesimplifier.cpp b/lib/templatesimplifier.cpp index 1478af7db..0e1fa2468 100644 --- a/lib/templatesimplifier.cpp +++ b/lib/templatesimplifier.cpp @@ -775,8 +775,11 @@ void TemplateSimplifier::simplifyTemplateAliases(std::listtokAt(2); while (tok2) { Token * const start = tok2; - while (tok2 && !Token::Match(tok2, "[,>;{}]")) + while (tok2 && !Token::Match(tok2, "[,>;{}]")) { + if (tok2->link() && Token::Match(tok2, "(|<|[")) + tok2 = tok2->link(); tok2 = tok2->next(); + } args.push_back(std::pair(start, tok2)); if (tok2 && tok2->str() == ",") { @@ -798,31 +801,41 @@ void TemplateSimplifier::simplifyTemplateAliases(std::listnext(); // the '<' - Token *tok1 = templateAlias.token->tokAt(2); - while (tok1 && tok1->str() != ";") { - Token *fromStart, *fromEnd; - if (aliasParameterNames.find(tok1->str()) != aliasParameterNames.end()) { - const unsigned int argnr = aliasParameterNames[tok1->str()]; - fromStart = args[argnr].first; - fromEnd = args[argnr].second->previous(); - } else { - fromStart = fromEnd = tok1; - } - - if (tok2->next() == fromStart) - tok2 = fromEnd; - else - tok2 = Tokenizer::copyTokens(tok2, fromStart, fromEnd, true); - tok1 = tok1->next(); + const Token * const endToken1 = templateAlias.token->next()->findClosingBracket(); + Token * const endToken2 = Tokenizer::copyTokens(tok2, templateAlias.token->tokAt(2), endToken1->previous(), false); + for (; tok2 != endToken2; tok2 = tok2->next()) { + if (!tok2->isName() || aliasParameterNames.find(tok2->str()) == aliasParameterNames.end()) + continue; + const unsigned int argnr = aliasParameterNames[tok2->str()]; + const Token * const fromStart = args[argnr].first; + const Token * const fromEnd = args[argnr].second->previous(); + Token * const destToken = tok2; + tok2 = Tokenizer::copyTokens(tok2, fromStart, fromEnd, true); + destToken->deleteThis(); } - endToken = tok1; - Token::eraseTokens(tok2, args.back().second->next()); + + endToken = endToken1->next(); + + Token::eraseTokens(tok2, args.back().second); } if (endToken) { + // Remove all template instantiations in template alias + for (const Token *tok = startToken; tok != endToken; tok = tok->next()) { + if (!Token::Match(tok, "%name% <")) + continue; + std::list::iterator it = std::find_if(templateInstantiations->begin(), + templateInstantiations->end(), + FindToken(tok)); + if (it == templateInstantiations->end()) + continue; + if (it == it1) + it1++; + std::list::iterator next = it; + next++; + templateInstantiations->erase(it,next); + } + Token::eraseTokens(startToken, endToken); - it2 = it1; - --it2; - templateInstantiations->erase(it2,it1); } } } diff --git a/test/testsimplifytemplate.cpp b/test/testsimplifytemplate.cpp index 09c2725a9..1a3b47d3b 100644 --- a/test/testsimplifytemplate.cpp +++ b/test/testsimplifytemplate.cpp @@ -124,6 +124,7 @@ private: TEST_CASE(templateAlias1); TEST_CASE(templateAlias2); + TEST_CASE(templateAlias3); // #8315 // Test TemplateSimplifier::instantiateMatch TEST_CASE(instantiateMatch); @@ -1607,6 +1608,14 @@ private: ASSERT_EQUALS(expected, tok(code)); } + void templateAlias3() { // #8315 + const char code[] = "template struct Tag {};\n" + "template using SPtr = std::shared_ptr)>;\n" + "SPtr<0> s;"; + const char expected[] = "template < int > struct Tag { } ; std :: shared_ptr < void ( Tag < 0 > ) > s ;"; + ASSERT_EQUALS(expected, tok(code)); + } + unsigned int instantiateMatch(const char code[], const std::size_t numberOfArguments, const char patternAfter[]) { Tokenizer tokenizer(&settings, this);