dereferencing deallocated memory: it is ok to take the address to deallocated memory but it is not ok to dereference the address

This commit is contained in:
Daniel Marjamäki 2009-07-21 13:04:13 +02:00
parent 45f8560537
commit 6f646246ee
3 changed files with 28 additions and 64 deletions

View File

@ -273,7 +273,7 @@ void CheckMemoryLeak::deallocDeallocError(const Token *tok, const std::string &v
void CheckMemoryLeak::deallocuseError(const Token *tok, const std::string &varname) void CheckMemoryLeak::deallocuseError(const Token *tok, const std::string &varname)
{ {
errorLogger->reportErr(errmsg(tok, Severity::error, "deallocuse", "Using '" + varname + "' after it is deallocated / released")); errorLogger->reportErr(errmsg(tok, Severity::error, "deallocuse", "Dereferencing '" + varname + "' after it is deallocated / released"));
} }
void CheckMemoryLeak::mismatchSizeError(const Token *tok, const std::string &sz) void CheckMemoryLeak::mismatchSizeError(const Token *tok, const std::string &sz)
@ -1515,7 +1515,7 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const char varname
while (Token::Match(tok2, "[;{}] ;")) while (Token::Match(tok2, "[;{}] ;"))
Token::eraseTokens(tok2, tok2->tokAt(2)); Token::eraseTokens(tok2, tok2->tokAt(2));
} }
if ((result = Token::findmatch(tok, "[;{}] dealloc [;{}] use|use_ ;")) != NULL) if ((result = Token::findmatch(tok, "[;{}] dealloc ; use_ ;")) != NULL)
{ {
deallocuseError(result->tokAt(3), varname); deallocuseError(result->tokAt(3), varname);
} }

View File

@ -66,7 +66,7 @@ private:
check(filedata); check(filedata);
// Compare results.. // Compare results..
ASSERT_EQUALS("[file.cpp:5]: (error) Using 'foo' after it is deallocated / released\n", errout.str()); ASSERT_EQUALS("[file.cpp:5]: (error) Dereferencing 'foo' after it is deallocated / released\n", errout.str());
} }
void linenumbers2() void linenumbers2()

View File

@ -232,16 +232,10 @@ private:
TEST_CASE(cast2); TEST_CASE(cast2);
TEST_CASE(cast3); TEST_CASE(cast3);
// Using deallocated memory:
TEST_CASE(structmember1); // * It is ok to take the address to deallocated memory
// * It is not ok to dereference a pointer to deallocated memory
TEST_CASE(dealloc_use_1); // Deallocate and then use memory TEST_CASE(dealloc_use);
TEST_CASE(dealloc_use_2); // Deallocate and then use memory. No error if "use" is &var
TEST_CASE(dealloc_use_3); // Deallocate and then use memory. No error
TEST_CASE(dealloc_use_4);
TEST_CASE(dealloc_use_5);
TEST_CASE(dealloc_use_6);
TEST_CASE(dealloc_use_7);
// free a free'd pointer // free a free'd pointer
TEST_CASE(freefree1); TEST_CASE(freefree1);
@ -1771,34 +1765,26 @@ private:
void structmember1() void dealloc_use()
{
check("void f()\n"
"{\n"
" struct ABC *abc = new ABC;\n"
" abc->a = new char[100];\n"
" delete abc;\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Memory leak: abc.a\n", errout.str());
}
void dealloc_use_1()
{ {
// It is ok to take the address..
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char *s = new char[100];\n" " char *s = new char[100];\n"
" delete [] s;\n" " delete [] s;\n"
" p = s;\n" " p = s;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Using 's' after it is deallocated / released\n", errout.str()); ASSERT_EQUALS("", errout.str());
}
void dealloc_use_2() check("void f()\n"
{ "{\n"
" char *s = new char[100];\n"
" delete [] s;\n"
" foo(s);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// The pointer to the pointer is valid..
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" char *str;\n" " char *str;\n"
@ -1806,10 +1792,7 @@ private:
" foo(&str);\n" " foo(&str);\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
}
void dealloc_use_3()
{
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" char *str = 0;\n" " char *str = 0;\n"
@ -1818,50 +1801,31 @@ private:
" f2(str);\n" " f2(str);\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
}
void dealloc_use_4() // Dereferencing the freed pointer is not ok..
{ check("void foo()\n"
check("static void ReadDir(DIR *d)\n"
"{\n" "{\n"
" DIR *subdir = OpenDir();\n" " char *str = malloc(10);\n"
" ReadDir( subdir );\n" " free(str);\n"
" closedir(subdir);\n" " char c = *str;\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); TODO_ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
}
void dealloc_use_5()
{
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" char *str = malloc(10);\n" " char *str = malloc(10);\n"
" free(str);\n" " free(str);\n"
" char c = str[10];\n" " char c = str[10];\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Using 'str' after it is deallocated / released\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
}
void dealloc_use_6()
{
check("void foo()\n" check("void foo()\n"
"{\n" "{\n"
" char *str = 0;\n" " char *str = malloc(10);\n"
" free(str);\n" " free(str);\n"
" printf(\"free %x\", str);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void dealloc_use_7()
{
check("void foo()\n"
"{\n"
" char *str = new char[10];\n"
" delete [] str;\n"
" str[10] = 0;\n" " str[10] = 0;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:5]: (error) Using 'str' after it is deallocated / released\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (error) Dereferencing 'str' after it is deallocated / released\n", errout.str());
} }