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; const Library * const lib = &settings->library;
bool isContainer = false;
if (mNameToken) if (mNameToken)
setFlag(fIsArray, arrayDimensions(settings)); setFlag(fIsArray, arrayDimensions(settings, &isContainer));
if (mTypeStartToken) if (mTypeStartToken)
setValueType(ValueType::parseDecl(mTypeStartToken,settings)); setValueType(ValueType::parseDecl(mTypeStartToken,settings));
@ -2008,7 +2009,7 @@ void Variable::evaluate(const Settings* settings)
setFlag(fIsConst, true); setFlag(fIsConst, true);
setFlag(fIsStatic, true); setFlag(fIsStatic, true);
} else if (tok->str() == "*") { } 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 setFlag(fIsConst, false); // Points to const, isn't necessarily const itself
} else if (tok->str() == "&") { } else if (tok->str() == "&") {
if (isReference()) if (isReference())
@ -2053,7 +2054,7 @@ void Variable::evaluate(const Settings* settings)
tok = tok->link()->previous(); tok = tok->link()->previous();
// add array dimensions if present // add array dimensions if present
if (tok && tok->next()->str() == "[") if (tok && tok->next()->str() == "[")
setFlag(fIsArray, arrayDimensions(settings)); setFlag(fIsArray, arrayDimensions(settings, &isContainer));
} }
if (!tok) if (!tok)
return; return;
@ -3243,12 +3244,14 @@ bool Type::isDerivedFrom(const std::string & ancestor) const
return false; 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); const Library::Container* container = settings->library.detectContainer(mTypeStartToken);
if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) { if (container && container->arrayLike_indexOp && container->size_templateArgNo > 0) {
const Token* tok = Token::findsimplematch(mTypeStartToken, "<"); const Token* tok = Token::findsimplematch(mTypeStartToken, "<");
if (tok) { if (tok) {
*isContainer = true;
Dimension dimension_; Dimension dimension_;
tok = tok->next(); tok = tok->next();
for (int i = 0; i < container->size_templateArgNo && tok; i++) { 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 * @brief parse and save array dimension information
* @param settings Platform settings and library * @param settings Platform settings and library
* @param isContainer Is the array container-like?
* @return true if array, false if not * @return true if array, false if not
*/ */
bool arrayDimensions(const Settings* settings); bool arrayDimensions(const Settings* settings, bool* isContainer);
public: public:
Variable(const Token *name_, const Token *start_, const Token *end_, Variable(const Token *name_, const Token *start_, const Token *end_,

View File

@ -746,6 +746,14 @@ private:
" free((char **)args2);\n" " free((char **)args2);\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); 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() { void testinvaliddealloc_C() {

View File

@ -1792,6 +1792,13 @@ private:
"}"); "}");
ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: vertices\n", ASSERT_EQUALS("[test.cpp:4]: (error) Uninitialized variable: vertices\n",
errout.str()); 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 void uninitvar_cpp11ArrayInit() { // #7010