Added auto_ptr checking for malloc
This commit is contained in:
parent
e5e7c5dc8b
commit
a49efb13f6
@ -1232,7 +1232,9 @@ static bool hasArrayEndParen(const Token *tok1)
|
|||||||
void CheckStl::checkAutoPointer()
|
void CheckStl::checkAutoPointer()
|
||||||
{
|
{
|
||||||
std::set<unsigned int> autoPtrVarId;
|
std::set<unsigned int> autoPtrVarId;
|
||||||
|
std::map<unsigned int, const std::string> mallocVarId; // variables allocated by the malloc-like function
|
||||||
static const char STL_CONTAINER_LIST[] = "array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|vector|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset|basic_string";
|
static const char STL_CONTAINER_LIST[] = "array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|vector|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset|basic_string";
|
||||||
|
const int malloc = _settings->library.alloc("malloc"); // allocation function, which are not compatible with auto_ptr
|
||||||
|
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "auto_ptr <")) {
|
if (Token::simpleMatch(tok, "auto_ptr <")) {
|
||||||
@ -1247,6 +1249,17 @@ void CheckStl::checkAutoPointer()
|
|||||||
if (Token::Match(tok3, "( new %type%") && hasArrayEndParen(tok3)) {
|
if (Token::Match(tok3, "( new %type%") && hasArrayEndParen(tok3)) {
|
||||||
autoPointerArrayError(tok2->next());
|
autoPointerArrayError(tok2->next());
|
||||||
}
|
}
|
||||||
|
if (Token::Match(tok3, "( %name% (") && malloc && _settings->library.alloc(tok3->next()) == malloc) {
|
||||||
|
// malloc-like function allocated memory passed to the auto_ptr constructor -> error
|
||||||
|
autoPointerMallocError(tok2->next(), tok3->next()->str());
|
||||||
|
}
|
||||||
|
if (Token::Match(tok3, "( %var%")) {
|
||||||
|
std::map<unsigned int, const std::string>::const_iterator it = mallocVarId.find(tok3->next()->varId());
|
||||||
|
if (it != mallocVarId.cend()) {
|
||||||
|
// pointer on the memory allocated by malloc used in the auto pointer constructor -> error
|
||||||
|
autoPointerMallocError(tok2->next(), it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
while (tok3 && tok3->str() != ";") {
|
while (tok3 && tok3->str() != ";") {
|
||||||
tok3 = tok3->next();
|
tok3 = tok3->next();
|
||||||
}
|
}
|
||||||
@ -1280,6 +1293,21 @@ void CheckStl::checkAutoPointer()
|
|||||||
if (iter != autoPtrVarId.end()) {
|
if (iter != autoPtrVarId.end()) {
|
||||||
autoPointerArrayError(tok);
|
autoPointerArrayError(tok);
|
||||||
}
|
}
|
||||||
|
} else if (Token::Match(tok, "%var% = %name% (") && malloc && _settings->library.alloc(tok->tokAt(2)) == malloc) {
|
||||||
|
// C library function like 'malloc' used together with auto pointer -> error
|
||||||
|
std::set<unsigned int>::const_iterator iter = autoPtrVarId.find(tok->varId());
|
||||||
|
if (iter != autoPtrVarId.end()) {
|
||||||
|
autoPointerMallocError(tok, tok->strAt(2));
|
||||||
|
} else if (tok->varId()) {
|
||||||
|
// it is not an auto pointer variable and it is allocated by malloc like function.
|
||||||
|
mallocVarId.insert(std::make_pair(tok->varId(), tok->strAt(2)));
|
||||||
|
}
|
||||||
|
} else if (Token::Match(tok, "%var% . reset ( %name% (") && malloc && _settings->library.alloc(tok->tokAt(4)) == malloc) {
|
||||||
|
// C library function like 'malloc' used when resetting auto pointer -> error
|
||||||
|
std::set<unsigned int>::const_iterator iter = autoPtrVarId.find(tok->varId());
|
||||||
|
if (iter != autoPtrVarId.end()) {
|
||||||
|
autoPointerMallocError(tok, tok->strAt(4));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1310,6 +1338,13 @@ void CheckStl::autoPointerArrayError(const Token *tok)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckStl::autoPointerMallocError(const Token *tok, const std::string& allocFunction)
|
||||||
|
{
|
||||||
|
const std::string summary = "Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function '" + allocFunction + "'.";
|
||||||
|
const std::string verbose = summary + " This means that you should only use 'auto_ptr' for pointers obtained with operator 'new'. This excludes use C library allocation functions (for example '" + allocFunction + "'), which must be deallocated by the appropriate C library function.";
|
||||||
|
reportError(tok, Severity::error, "useAutoPointerMalloc", summary + "\n" + verbose);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckStl::uselessCalls()
|
void CheckStl::uselessCalls()
|
||||||
{
|
{
|
||||||
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
// THIS ARRAY MUST BE ORDERED ALPHABETICALLY
|
||||||
|
@ -178,6 +178,7 @@ private:
|
|||||||
void autoPointerError(const Token *tok);
|
void autoPointerError(const Token *tok);
|
||||||
void autoPointerContainerError(const Token *tok);
|
void autoPointerContainerError(const Token *tok);
|
||||||
void autoPointerArrayError(const Token *tok);
|
void autoPointerArrayError(const Token *tok);
|
||||||
|
void autoPointerMallocError(const Token *tok, const std::string& allocFunction);
|
||||||
|
|
||||||
void uselessCallsReturnValueError(const Token *tok, const std::string &varname, const std::string &function);
|
void uselessCallsReturnValueError(const Token *tok, const std::string &varname, const std::string &function);
|
||||||
void uselessCallsSwapError(const Token *tok, const std::string &varname);
|
void uselessCallsSwapError(const Token *tok, const std::string &varname);
|
||||||
@ -210,6 +211,7 @@ private:
|
|||||||
c.autoPointerError(0);
|
c.autoPointerError(0);
|
||||||
c.autoPointerContainerError(0);
|
c.autoPointerContainerError(0);
|
||||||
c.autoPointerArrayError(0);
|
c.autoPointerArrayError(0);
|
||||||
|
c.autoPointerMallocError(0, "malloc");
|
||||||
c.uselessCallsReturnValueError(0, "str", "find");
|
c.uselessCallsReturnValueError(0, "str", "find");
|
||||||
c.uselessCallsSwapError(0, "str");
|
c.uselessCallsSwapError(0, "str");
|
||||||
c.uselessCallsSubstrError(0, false);
|
c.uselessCallsSubstrError(0, false);
|
||||||
|
@ -2298,6 +2298,52 @@ private:
|
|||||||
" auto_ptr_array<char> domainName(new char[42]);\n"
|
" auto_ptr_array<char> domainName(new char[42]);\n"
|
||||||
"}");
|
"}");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// ticket #749
|
||||||
|
check("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" int *i = malloc(sizeof(int));\n"
|
||||||
|
" auto_ptr<int> x(i);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str());
|
||||||
|
|
||||||
|
check("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" auto_ptr<int> x((int*)malloc(sizeof(int)*4));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str());
|
||||||
|
|
||||||
|
check("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" auto_ptr<int> b(static_cast<int*>(malloc(sizeof(int)*4)));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str());
|
||||||
|
|
||||||
|
check("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" auto_ptr<int> x = (int*)malloc(sizeof(int)*4);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str());
|
||||||
|
|
||||||
|
check("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" auto_ptr<int> x = static_cast<int*>(malloc(sizeof(int)*4));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str());
|
||||||
|
|
||||||
|
check("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" auto_ptr<int> x;\n"
|
||||||
|
" x.reset((int*)malloc(sizeof(int)*4));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str());
|
||||||
|
|
||||||
|
check("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" auto_ptr<int> x;\n"
|
||||||
|
" x.reset(static_cast<int*>(malloc(sizeof(int)*4)));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (error) Object pointed by an 'auto_ptr' is destroyed using operator 'delete'. You should not use 'auto_ptr' for pointers obtained with function 'malloc'.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void uselessCalls() {
|
void uselessCalls() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user