Fix issue 10037: False positive when passing variables to functions by address (#2957)

This commit is contained in:
Paul Fultz II 2020-12-19 01:29:37 -06:00 committed by GitHub
parent 2541b6034f
commit 626dcd0eba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 0 deletions

View File

@ -3120,6 +3120,14 @@ static void valueFlowForwardLifetime(Token * tok, TokenList *tokenlist, ErrorLog
tokenlist,
errorLogger,
settings);
// Cast
} else if (parent->isCast()) {
std::list<ValueFlow::Value> values = tok->values();
// Only forward lifetime values
values.remove_if(&isNotLifetimeValue);
for(const ValueFlow::Value& value:values)
setTokenValue(parent, value, tokenlist->getSettings());
valueFlowForwardLifetime(parent, tokenlist, errorLogger, settings);
}
}

View File

@ -3479,6 +3479,21 @@ private:
" return d;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
// #10037
check("struct a {\n"
" int* p;\n"
"};\n"
"void g(a*);\n"
"void f() {\n"
" struct a b;\n"
" uint32_t p = (uint32_t) -1;\n"
" b.p = (void *) &p;\n"
" int r = g(&b);\n"
" if (r == 0)\n"
" if (p != (uint32_t) -1) {}\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void alwaysTrueInfer() {

View File

@ -147,6 +147,10 @@ private:
return !val.isTokValue();
}
static bool isNotLifetimeValue(const ValueFlow::Value& val) {
return !val.isLifetimeValue();
}
bool testValueOfXKnown(const char code[], unsigned int linenr, int value) {
// Tokenize..
Tokenizer tokenizer(&settings, this);
@ -371,6 +375,25 @@ private:
return values;
}
std::vector<std::string> lifetimeValues(const char code[], const char tokstr[], const Settings *s = nullptr) {
std::vector<std::string> result;
Tokenizer tokenizer(s ? s : &settings, this);
std::istringstream istr(code);
errout.str("");
tokenizer.tokenize(istr, "test.cpp");
const Token *tok = Token::findmatch(tokenizer.tokens(), tokstr);
if (!tok)
return result;
for(const ValueFlow::Value& value:tok->values()) {
if (!value.isLifetimeValue())
continue;
if (!value.tokvalue)
continue;
result.push_back(value.tokvalue->expressionString());
}
return result;
}
ValueFlow::Value valueOfTok(const char code[], const char tokstr[]) {
std::list<ValueFlow::Value> values = tokenValues(code, tokstr);
return values.size() == 1U && !values.front().isTokValue() ? values.front() : ValueFlow::Value();
@ -451,6 +474,7 @@ private:
void valueFlowLifetime() {
const char *code;
std::vector<std::string> lifetimes;
LOAD_LIB_2(settings.library, "std.cfg");
@ -482,6 +506,14 @@ private:
" auto it = x;\n"
"}\n";
ASSERT_EQUALS(true, testValueOfX(code, 4, "v . begin", ValueFlow::Value::LIFETIME));
code = "void f() {\n"
" int i = 0;\n"
" void* x = (void*)&i;\n"
"}\n";
lifetimes = lifetimeValues(code, "( void * )");
ASSERT_EQUALS(true, lifetimes.size() == 1);
ASSERT_EQUALS(true, lifetimes.front() == "i");
}
void valueFlowArrayElement() {