Fix #10097: autovarInvalidDeallocation with pointer to std::array (#3529)

This commit is contained in:
chrchr-github 2021-11-08 20:31:16 +01:00 committed by GitHub
parent b4561229cb
commit 629f883408
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 24 additions and 5 deletions

View File

@ -1981,8 +1981,9 @@ void Variable::evaluate(const Settings* settings)
const Library * const lib = &settings->library;
bool isContainer = false;
if (mNameToken)
setFlag(fIsArray, arrayDimensions(settings));
setFlag(fIsArray, arrayDimensions(settings, &isContainer));
if (mTypeStartToken)
setValueType(ValueType::parseDecl(mTypeStartToken,settings));
@ -2008,7 +2009,7 @@ void Variable::evaluate(const Settings* settings)
setFlag(fIsConst, true);
setFlag(fIsStatic, true);
} else if (tok->str() == "*") {
setFlag(fIsPointer, !isArray() || Token::Match(tok->previous(), "( * %name% )"));
setFlag(fIsPointer, !isArray() || (isContainer && !Token::Match(tok->next(), "%name% [")) || Token::Match(tok->previous(), "( * %name% )"));
setFlag(fIsConst, false); // Points to const, isn't necessarily const itself
} else if (tok->str() == "&") {
if (isReference())
@ -2053,7 +2054,7 @@ void Variable::evaluate(const Settings* settings)
tok = tok->link()->previous();
// add array dimensions if present
if (tok && tok->next()->str() == "[")
setFlag(fIsArray, arrayDimensions(settings));
setFlag(fIsArray, arrayDimensions(settings, &isContainer));
}
if (!tok)
return;
@ -3243,12 +3244,14 @@ bool Type::isDerivedFrom(const std::string & ancestor) const
return false;
}
bool Variable::arrayDimensions(const Settings* settings)
bool Variable::arrayDimensions(const Settings* settings, bool* isContainer)
{
*isContainer = false;
const Library::Container* container = settings->library.detectContainer(mTypeStartToken);
if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) {
const Token* tok = Token::findsimplematch(mTypeStartToken, "<");
if (tok) {
*isContainer = true;
Dimension dimension_;
tok = tok->next();
for (int i = 0; i < container->size_templateArgNo && tok; i++) {

View File

@ -215,9 +215,10 @@ class CPPCHECKLIB Variable {
/**
* @brief parse and save array dimension information
* @param settings Platform settings and library
* @param isContainer Is the array container-like?
* @return true if array, false if not
*/
bool arrayDimensions(const Settings* settings);
bool arrayDimensions(const Settings* settings, bool* isContainer);
public:
Variable(const Token *name_, const Token *start_, const Token *end_,

View File

@ -746,6 +746,14 @@ private:
" free((char **)args2);\n"
"}");
ASSERT_EQUALS("", errout.str());
// #10097
check("struct Array {\n"
" ~Array() { delete m_Arr; }\n"
" std::array<long, 256>* m_Arr{};\n"
"};\n"
"Array arr;\n");
ASSERT_EQUALS("", errout.str());
}
void testinvaliddealloc_C() {

View File

@ -1792,6 +1792,13 @@ private:
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: vertices\n",
errout.str());
checkUninitVar("void f() {\n"
" std::array<int, 3> *PArr[2] = { p0, p1 };\n"
" (*PArr[0])[2] = 0;\n"
" (*PArr[1])[2] = 0;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void uninitvar_cpp11ArrayInit() { // #7010