Fixed #8315 (heap use after free: templatesimplifier)
This commit is contained in:
parent
94790620d6
commit
04c57381ea
|
@ -775,8 +775,11 @@ void TemplateSimplifier::simplifyTemplateAliases(std::list<TemplateSimplifier::T
|
||||||
Token *tok2 = aliasUsage.token->tokAt(2);
|
Token *tok2 = aliasUsage.token->tokAt(2);
|
||||||
while (tok2) {
|
while (tok2) {
|
||||||
Token * const start = 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();
|
tok2 = tok2->next();
|
||||||
|
}
|
||||||
|
|
||||||
args.push_back(std::pair<Token *, Token *>(start, tok2));
|
args.push_back(std::pair<Token *, Token *>(start, tok2));
|
||||||
if (tok2 && tok2->str() == ",") {
|
if (tok2 && tok2->str() == ",") {
|
||||||
|
@ -798,31 +801,41 @@ void TemplateSimplifier::simplifyTemplateAliases(std::list<TemplateSimplifier::T
|
||||||
aliasUsage.token = tok2;
|
aliasUsage.token = tok2;
|
||||||
}
|
}
|
||||||
tok2 = aliasUsage.token->next(); // the '<'
|
tok2 = aliasUsage.token->next(); // the '<'
|
||||||
Token *tok1 = templateAlias.token->tokAt(2);
|
const Token * const endToken1 = templateAlias.token->next()->findClosingBracket();
|
||||||
while (tok1 && tok1->str() != ";") {
|
Token * const endToken2 = Tokenizer::copyTokens(tok2, templateAlias.token->tokAt(2), endToken1->previous(), false);
|
||||||
Token *fromStart, *fromEnd;
|
for (; tok2 != endToken2; tok2 = tok2->next()) {
|
||||||
if (aliasParameterNames.find(tok1->str()) != aliasParameterNames.end()) {
|
if (!tok2->isName() || aliasParameterNames.find(tok2->str()) == aliasParameterNames.end())
|
||||||
const unsigned int argnr = aliasParameterNames[tok1->str()];
|
continue;
|
||||||
fromStart = args[argnr].first;
|
const unsigned int argnr = aliasParameterNames[tok2->str()];
|
||||||
fromEnd = args[argnr].second->previous();
|
const Token * const fromStart = args[argnr].first;
|
||||||
} else {
|
const Token * const fromEnd = args[argnr].second->previous();
|
||||||
fromStart = fromEnd = tok1;
|
Token * const destToken = tok2;
|
||||||
}
|
tok2 = Tokenizer::copyTokens(tok2, fromStart, fromEnd, true);
|
||||||
|
destToken->deleteThis();
|
||||||
if (tok2->next() == fromStart)
|
|
||||||
tok2 = fromEnd;
|
|
||||||
else
|
|
||||||
tok2 = Tokenizer::copyTokens(tok2, fromStart, fromEnd, true);
|
|
||||||
tok1 = tok1->next();
|
|
||||||
}
|
}
|
||||||
endToken = tok1;
|
|
||||||
Token::eraseTokens(tok2, args.back().second->next());
|
endToken = endToken1->next();
|
||||||
|
|
||||||
|
Token::eraseTokens(tok2, args.back().second);
|
||||||
}
|
}
|
||||||
if (endToken) {
|
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<TokenAndName>::iterator it = std::find_if(templateInstantiations->begin(),
|
||||||
|
templateInstantiations->end(),
|
||||||
|
FindToken(tok));
|
||||||
|
if (it == templateInstantiations->end())
|
||||||
|
continue;
|
||||||
|
if (it == it1)
|
||||||
|
it1++;
|
||||||
|
std::list<TokenAndName>::iterator next = it;
|
||||||
|
next++;
|
||||||
|
templateInstantiations->erase(it,next);
|
||||||
|
}
|
||||||
|
|
||||||
Token::eraseTokens(startToken, endToken);
|
Token::eraseTokens(startToken, endToken);
|
||||||
it2 = it1;
|
|
||||||
--it2;
|
|
||||||
templateInstantiations->erase(it2,it1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE(templateAlias1);
|
TEST_CASE(templateAlias1);
|
||||||
TEST_CASE(templateAlias2);
|
TEST_CASE(templateAlias2);
|
||||||
|
TEST_CASE(templateAlias3); // #8315
|
||||||
|
|
||||||
// Test TemplateSimplifier::instantiateMatch
|
// Test TemplateSimplifier::instantiateMatch
|
||||||
TEST_CASE(instantiateMatch);
|
TEST_CASE(instantiateMatch);
|
||||||
|
@ -1607,6 +1608,14 @@ private:
|
||||||
ASSERT_EQUALS(expected, tok(code));
|
ASSERT_EQUALS(expected, tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void templateAlias3() { // #8315
|
||||||
|
const char code[] = "template <int> struct Tag {};\n"
|
||||||
|
"template <int ID> using SPtr = std::shared_ptr<void(Tag<ID>)>;\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[]) {
|
unsigned int instantiateMatch(const char code[], const std::size_t numberOfArguments, const char patternAfter[]) {
|
||||||
Tokenizer tokenizer(&settings, this);
|
Tokenizer tokenizer(&settings, this);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue