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:
parent
6635e6cc07
commit
18e00bb4fd
|
@ -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;
|
||||
|
|
|
@ -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() == ",") {
|
||||
|
|
|
@ -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, "[")) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue