Fixed #1374 (false negative: using uninitialized variable in printf)

This commit is contained in:
Alexander Mai 2014-03-06 06:16:14 +01:00 committed by Daniel Marjamäki
parent d53a6ca2cd
commit 1d4839b8a6
5 changed files with 42 additions and 12 deletions

View File

@ -56,7 +56,7 @@
<function name="wcstoul"> <leak-ignore/> <arg nr="3"><valid>0,2-36</valid></arg> </function> <function name="wcstoul"> <leak-ignore/> <arg nr="3"><valid>0,2-36</valid></arg> </function>
<function name="wcstoull"> <leak-ignore/> <arg nr="3"><valid>0,2-36</valid></arg> </function> <function name="wcstoull"> <leak-ignore/> <arg nr="3"><valid>0,2-36</valid></arg> </function>
<function name="printf"> <noreturn>false</noreturn> <formatstr/> <arg nr="1"><formatstr/></arg> </function> <function name="printf"> <noreturn>false</noreturn> <formatstr/> <arg nr="1"><formatstr/></arg> <arg nr="any"><not-uninit/></arg> </function>
<function name="wprintf"> <noreturn>false</noreturn> <formatstr/> <arg nr="1"><formatstr/></arg> </function> <function name="wprintf"> <noreturn>false</noreturn> <formatstr/> <arg nr="1"><formatstr/></arg> </function>
<function name="sprintf"> <noreturn>false</noreturn> <formatstr/> <arg nr="2"><formatstr/></arg> </function> <function name="sprintf"> <noreturn>false</noreturn> <formatstr/> <arg nr="2"><formatstr/></arg> </function>
<function name="fprintf"> <noreturn>false</noreturn> <formatstr/> <arg nr="2"><formatstr/></arg> </function> <function name="fprintf"> <noreturn>false</noreturn> <formatstr/> <arg nr="2"><formatstr/></arg> </function>

View File

@ -137,7 +137,8 @@ bool Library::load(const tinyxml2::XMLDocument &doc)
else if (strcmp(functionnode->Name(),"leak-ignore")==0) else if (strcmp(functionnode->Name(),"leak-ignore")==0)
leakignore.insert(name); leakignore.insert(name);
else if (strcmp(functionnode->Name(), "arg") == 0 && functionnode->Attribute("nr") != nullptr) { else if (strcmp(functionnode->Name(), "arg") == 0 && functionnode->Attribute("nr") != nullptr) {
const int nr = atoi(functionnode->Attribute("nr")); const bool bAnyArg = strcmp(functionnode->Attribute("nr"),"any")==0;
const int nr = (bAnyArg) ? -1 : atoi(functionnode->Attribute("nr"));
bool notbool = false; bool notbool = false;
bool notnull = false; bool notnull = false;
bool notuninit = false; bool notuninit = false;
@ -310,3 +311,17 @@ bool Library::isargvalid(const std::string &functionName, int argnr, const MathL
} }
return false; return false;
} }
const Library::ArgumentChecks * Library::getarg(const std::string &functionName, int argnr) const
{
std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it1;
it1 = argumentChecks.find(functionName);
if (it1 == argumentChecks.end())
return nullptr;
const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.find(argnr);
if (it2 != it1->second.end())
return &it2->second;
const std::map<int,ArgumentChecks>::const_iterator it3 = it1->second.find(-1);
if (it3 != it1->second.end())
return &it3->second;
}

View File

@ -342,16 +342,7 @@ private:
std::map<std::string, std::pair<bool, bool> > _formatstr; // Parameters for format string checking std::map<std::string, std::pair<bool, bool> > _formatstr; // Parameters for format string checking
const ArgumentChecks * getarg(const std::string &functionName, int argnr) const { const ArgumentChecks * getarg(const std::string &functionName, int argnr) const;
std::map<std::string, std::map<int, ArgumentChecks> >::const_iterator it1;
it1 = argumentChecks.find(functionName);
if (it1 != argumentChecks.end()) {
const std::map<int,ArgumentChecks>::const_iterator it2 = it1->second.find(argnr);
if (it2 != it1->second.end())
return &it2->second;
}
return NULL;
}
static int getid(const std::map<std::string,int> &data, const std::string &name) { static int getid(const std::map<std::string,int> &data, const std::string &name) {
const std::map<std::string,int>::const_iterator it = data.find(name); const std::map<std::string,int>::const_iterator it = data.find(name);

View File

@ -971,6 +971,14 @@ Checking noreturn.c...
<literal>&lt;not-null&gt;</literal> and <literal>&lt;not-null&gt;</literal> and
<literal>&lt;not-uninit&gt;</literal> is correct.</para> <literal>&lt;not-uninit&gt;</literal> is correct.</para>
</section> </section>
<section>
<title>Specifications for all arguments</title>
<para>Specifying <literal>-1</literal> as the argument number is going
to apply a check to all arguments of that function. The specifications
for individual arguments override this setting.</para>
</section>
</chapter> </chapter>
<chapter> <chapter>

View File

@ -32,6 +32,7 @@ private:
TEST_CASE(empty); TEST_CASE(empty);
TEST_CASE(function); TEST_CASE(function);
TEST_CASE(function_arg); TEST_CASE(function_arg);
TEST_CASE(function_arg_any);
TEST_CASE(memory); TEST_CASE(memory);
TEST_CASE(resource); TEST_CASE(resource);
} }
@ -91,6 +92,21 @@ private:
ASSERT_EQUALS(true, library.argumentChecks["foo"][6].notbool); ASSERT_EQUALS(true, library.argumentChecks["foo"][6].notbool);
} }
void function_arg_any() {
const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<def>\n"
"<function name=\"foo\">\n"
" <arg nr=\"any\"><not-uninit/></arg>\n"
"</function>\n"
"</def>";
tinyxml2::XMLDocument doc;
doc.Parse(xmldata, sizeof(xmldata));
Library library;
library.load(doc);
ASSERT_EQUALS(true, library.argumentChecks["foo"][-1].notuninit);
}
void memory() { void memory() {
const char xmldata[] = "<?xml version=\"1.0\"?>\n" const char xmldata[] = "<?xml version=\"1.0\"?>\n"
"<def>\n" "<def>\n"