Fix #10817 Crash in checkPassByReference() / #10810 Stack overflow with decltype / #10763 Crash on invalid code (#3840)

* Fix #10817 Crash in checkPassByReference()

* Format

* Fix #10810 Stack overflow with decltype

* Fix #10763 Crash on invalid code in TemplateSimplifier::templateParameters
This commit is contained in:
chrchr-github 2022-02-18 12:59:21 +01:00 committed by GitHub
parent 6635e6cc07
commit 18e00bb4fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 9 deletions

View File

@ -1301,14 +1301,18 @@ void CheckOther::checkPassByReference()
bool inconclusive = false;
if (var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER && !var->valueType()->container->view) {} else if (var->type() && !var->type()->isEnumType()) { // Check if type is a struct or class.
// Ensure that it is a large object.
if (!var->type()->classScope)
inconclusive = true;
else if (estimateSize(var->type(), mSettings, symbolDatabase) <= 2 * mSettings->sizeof_pointer)
const bool isContainer = var->valueType() && var->valueType()->type == ValueType::Type::CONTAINER && var->valueType()->container && !var->valueType()->container->view;
if (!isContainer) {
if (var->type() && !var->type()->isEnumType()) { // Check if type is a struct or class.
// Ensure that it is a large object.
if (!var->type()->classScope)
inconclusive = true;
else if (estimateSize(var->type(), mSettings, symbolDatabase) <= 2 * mSettings->sizeof_pointer)
continue;
}
else
continue;
} else
continue;
}
if (inconclusive && !mSettings->certainty.isEnabled(Certainty::inconclusive))
continue;

View File

@ -402,6 +402,8 @@ unsigned int TemplateSimplifier::templateParameters(const Token *tok)
if (closing->str() == ">>")
return numberOfParameters;
tok = closing->next();
if (!tok)
syntaxError(tok);
if (Token::Match(tok, ">|>>|>>="))
return numberOfParameters;
else if (tok->str() == ",") {

View File

@ -2244,6 +2244,7 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok)
return nullptr;
if (typeTok != nullptr)
*typeTok = tok;
const Token* lhsVarTok{};
if (Token::simpleMatch(tok, "return")) {
const Scope *scope = tok->scope();
if (!scope)
@ -2266,8 +2267,8 @@ const ::Type* Token::typeOf(const Token* tok, const Token** typeTok)
return function->retType;
} else if (Token::Match(tok->previous(), "%type%|= (|{")) {
return typeOf(tok->previous(), typeTok);
} else if (Token::simpleMatch(tok, "=")) {
return Token::typeOf(getLHSVariableToken(tok), typeTok);
} else if (Token::simpleMatch(tok, "=") && (lhsVarTok = getLHSVariableToken(tok)) != tok->next()) {
return Token::typeOf(lhsVarTok, typeTok);
} else if (Token::simpleMatch(tok, ".")) {
return Token::typeOf(tok->astOperand2(), typeTok);
} else if (Token::simpleMatch(tok, "[")) {

View File

@ -251,6 +251,7 @@ private:
TEST_CASE(garbageCode219); // #10101
TEST_CASE(garbageCode220); // #6832
TEST_CASE(garbageCode221);
TEST_CASE(garbageCode222); // #10763
TEST_CASE(garbageCodeFuzzerClientMode1); // test cases created with the fuzzer client, mode 1
@ -1708,6 +1709,9 @@ private:
void garbageCode221() {
ASSERT_THROW(checkCode("struct A<0<;\n"), InternalError); // don't crash
}
void garbageCode222() { // #10763
ASSERT_THROW(checkCode("template<template<class>\n"), InternalError); // don't crash
}
void syntaxErrorFirstToken() {
ASSERT_THROW(checkCode("&operator(){[]};"), InternalError); // #7818

View File

@ -8520,6 +8520,10 @@ private:
" A a2;"
"};", nullptr, false, false, true);
ASSERT_EQUALS("[test.cpp:8]: (performance) Function parameter 'a2' should be passed by const reference.\n", errout.str());
check("std::map<int, int> m;\n" // #10817
"void f(const decltype(m)::const_iterator i) {}");
ASSERT_EQUALS("", errout.str());
}
void checkComparisonFunctionIsAlwaysTrueOrFalse() {

View File

@ -687,6 +687,18 @@ private:
lifetimes = lifetimeValues(code, "( void * )");
ASSERT_EQUALS(true, lifetimes.size() == 1);
ASSERT_EQUALS(true, lifetimes.front() == "i");
code = "struct T {\n" // #10810
" static int g() { return 0; }\n"
"};\n"
"T t;\n"
"struct S { int i; };\n"
"S f() {\n"
" S s = { decltype(t)::g() };\n"
" return s;\n"
"};\n";
lifetimes = lifetimeValues(code, "=");
ASSERT_EQUALS(true, lifetimes.empty());
}
void valueFlowArrayElement() {