Fixed #3245 (False positive: Dangerous usage of 'string' (strncpy doesn't always 0-terminate it))

This commit is contained in:
Daniel Marjamäki 2011-10-29 19:11:42 +02:00
parent 8f49eb6a7e
commit 316aa920eb
2 changed files with 55 additions and 14 deletions

View File

@ -240,17 +240,22 @@ private:
if (mode == 0 && (c->array || (c->pointer && c->alloc)))
continue;
// mode 2 : bad usage of pointer. if it's not a pointer then the usage is ok.
// mode 2 : reading array data with mem.. function. It's ok if the
// array is not 0-terminated
if (mode == 2 && c->strncpy_)
continue;
// mode 3 : bad usage of pointer. if it's not a pointer then the usage is ok.
// example: ptr->foo();
if (mode == 2 && !c->pointer)
if (mode == 3 && !c->pointer)
continue;
// mode 3 : using dead pointer is invalid.
if (mode == 3 && (!c->pointer || c->alloc))
// mode 4 : using dead pointer is invalid.
if (mode == 4 && (!c->pointer || c->alloc))
continue;
// mode 4 : reading uninitialized array or pointer is invalid.
if (mode == 4 && (!c->array && !c->pointer))
// mode 5 : reading uninitialized array or pointer is invalid.
if (mode == 5 && (!c->array && !c->pointer))
continue;
CheckUninitVar *checkUninitVar = dynamic_cast<CheckUninitVar *>(c->owner);
@ -290,6 +295,15 @@ private:
use(checks, tok, 1);
}
/**
* Reading array elements with a "mem.." function. It's ok if the array is not 0-terminated.
* @param checks all available checks
* @param tok variable token
*/
static void use_array_mem(std::list<ExecutionPath *> &checks, const Token *tok) {
use(checks, tok, 2);
}
/**
* Bad pointer usage. If the variable is not a pointer then the usage is ok.
* @param checks all available checks
@ -297,7 +311,7 @@ private:
* @return if error is found, true is returned
*/
static bool use_pointer(std::list<ExecutionPath *> &checks, const Token *tok) {
return use(checks, tok, 2);
return use(checks, tok, 3);
}
/**
@ -307,7 +321,7 @@ private:
* @return if error is found, true is returned
*/
static bool use_dead_pointer(std::list<ExecutionPath *> &checks, const Token *tok) {
return use(checks, tok, 3);
return use(checks, tok, 4);
}
/**
@ -318,10 +332,9 @@ private:
* @return if error is found, true is returned
*/
static bool use_array_or_pointer_data(std::list<ExecutionPath *> &checks, const Token *tok) {
return use(checks, tok, 4);
return use(checks, tok, 5);
}
/** declaring a variable */
void declare(std::list<ExecutionPath *> &checks, const Token *vartok, const Token &tok, const bool p, const bool a) const {
if (vartok->varId() == 0)
@ -576,7 +589,12 @@ private:
std::list<const Token *> var;
CheckNullPointer::parseFunctionCall(tok, var, 1);
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it) {
use_array(checks, *it);
// is function memset/memcpy/etc?
if (tok.str().compare(0,3,"mem") == 0)
use_array_mem(checks, *it);
else
use_array(checks, *it);
use_dead_pointer(checks, *it);
}
@ -839,10 +857,16 @@ private:
use_array_or_pointer_data(checks, tok.str() == "!" ? tok.next() : &tok);
else if (Token::Match(&tok, "!| %var% (")) {
const Token * const ftok = (tok.str() == "!") ? tok.next() : &tok;
std::list<const Token *> var;
CheckNullPointer::parseFunctionCall(tok.str() == "!" ? *tok.next() : tok, var, 1);
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it)
use_array(checks, *it);
CheckNullPointer::parseFunctionCall(*ftok, var, 1);
for (std::list<const Token *>::const_iterator it = var.begin(); it != var.end(); ++it) {
// is function memset/memcpy/etc?
if (ftok->str().compare(0,3,"mem") == 0)
use_array_mem(checks, *it);
else
use_array(checks, *it);
}
}
else if (Token::Match(&tok, "! %var% )")) {

View File

@ -1330,6 +1330,23 @@ private:
" strncat(a, \"world\", 20);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// #3245 - false positive
{
checkUninitVar("void f() {\n"
" char a[100];\n"
" strncpy(a,p,10);\n"
" memcmp(a,q,10);\n"
"}");
ASSERT_EQUALS("", errout.str());
checkUninitVar("void f() {\n"
" char a[100];\n"
" strncpy(a,p,10);\n"
" if (memcmp(a,q,10)==0);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
}
// initialization with memset (not 0-terminating string)..