Skip to content

Commit a1fafa7

Browse files
committed
Library: added <formatstr> and <strz> to argument checks
1 parent 20f81f9 commit a1fafa7

5 files changed

Lines changed: 69 additions & 5 deletions

File tree

lib/checkio.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,26 @@ void CheckIO::checkWrongPrintfScanfArguments()
439439
const Token* argListTok = 0; // Points to first va_list argument
440440
std::string formatString;
441441

442-
if (Token::Match(tok, "printf|scanf|wprintf|wscanf ( %str%")) {
442+
if (Token::Match(tok->next(), "( %any%")) {
443+
const Token *arg = tok->tokAt(2);
444+
int argnr = 1;
445+
while (arg) {
446+
if (Token::Match(arg, "%str% [,)]") && _settings->library.isargformatstr(tok->str(),argnr)) {
447+
formatString = arg->str();
448+
if (arg->strAt(1) == ",")
449+
argListTok = arg->tokAt(2);
450+
else
451+
argListTok = 0;
452+
break;
453+
}
454+
455+
arg = arg->nextArgument();
456+
argnr++;
457+
}
458+
}
459+
460+
if (!formatString.empty()) { /* formatstring found in library */ }
461+
else if (Token::Match(tok, "printf|scanf|wprintf|wscanf ( %str%")) {
443462
formatString = tok->strAt(2);
444463
if (tok->strAt(3) == ",") {
445464
argListTok = tok->tokAt(4);

lib/library.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,24 @@ bool Library::load(const char exename[], const char path[])
121121
const int nr = atoi(functionnode->Attribute("nr"));
122122
bool notnull = false;
123123
bool notuninit = false;
124+
bool formatstr = false;
125+
bool strz = false;
124126
for (const tinyxml2::XMLElement *argnode = functionnode->FirstChildElement(); argnode; argnode = argnode->NextSiblingElement()) {
125127
if (strcmp(argnode->Name(), "not-null") == 0)
126128
notnull = true;
127129
else if (strcmp(argnode->Name(), "not-uninit") == 0)
128130
notuninit = true;
131+
else if (strcmp(argnode->Name(), "formatstr") == 0)
132+
notuninit = true;
133+
else if (strcmp(argnode->Name(), "strz") == 0)
134+
notuninit = true;
129135
else
130136
return false;
131137
}
132138
argumentChecks[name][nr].notnull = notnull;
133139
argumentChecks[name][nr].notuninit = notuninit;
140+
argumentChecks[name][nr].formatstr = formatstr;
141+
argumentChecks[name][nr].strz = strz;
134142
} else
135143
return false;
136144
}

lib/library.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,14 @@ class CPPCHECKLIB Library {
8181
}
8282

8383
struct ArgumentChecks {
84+
ArgumentChecks() {
85+
notnull = notuninit = formatstr = strz = false;
86+
}
87+
8488
bool notnull;
8589
bool notuninit;
90+
bool formatstr;
91+
bool strz;
8692
};
8793

8894
// function name, argument nr => argument data
@@ -98,6 +104,16 @@ class CPPCHECKLIB Library {
98104
return arg && arg->notuninit;
99105
}
100106

107+
bool isargformatstr(const std::string &functionName, int argnr) const {
108+
const ArgumentChecks *arg = getarg(functionName,argnr);
109+
return arg && arg->formatstr;
110+
}
111+
112+
bool isargstrz(const std::string &functionName, int argnr) const {
113+
const ArgumentChecks *arg = getarg(functionName,argnr);
114+
return arg && arg->strz;
115+
}
116+
101117
std::set<std::string> returnuninitdata;
102118

103119
private:

test/testio.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ class TestIO : public TestFixture {
4848
TEST_CASE(testPrintfArgument);
4949

5050
TEST_CASE(testMicrosoftPrintfArgument); // ticket #4902
51+
52+
TEST_CASE(testlibrarycfg); // library configuration
5153
}
5254

53-
void check(const char code[], bool inconclusive = false, bool portability = false, Settings::PlatformType platform = Settings::Unspecified) {
55+
void check(const char code[], bool inconclusive = false, bool portability = false, Settings::PlatformType platform = Settings::Unspecified, Library *lib = NULL) {
5456
// Clear the error buffer..
5557
errout.str("");
5658

@@ -62,6 +64,9 @@ class TestIO : public TestFixture {
6264
settings.inconclusive = inconclusive;
6365
settings.platform(platform);
6466

67+
if (lib)
68+
settings.library = *lib;
69+
6570
// Tokenize..
6671
Tokenizer tokenizer(&settings, this);
6772
std::istringstream istr(code);
@@ -797,6 +802,22 @@ class TestIO : public TestFixture {
797802
"[test.cpp:12]: (warning) %I64u in format string (no. 2) requires an unsigned integer given in the argument list.\n"
798803
"[test.cpp:13]: (warning) %I64d in format string (no. 1) requires a signed integer given in the argument list.\n", errout.str());
799804
}
805+
806+
void testlibrarycfg() {
807+
const char code[] = "void f() {\n"
808+
" format(\"%s\");\n"
809+
"}";
810+
811+
// no error if configuration for 'format' is not provided
812+
check(code);
813+
ASSERT_EQUALS("", errout.str());
814+
815+
// error if configuration for 'format' is provided
816+
Library lib;
817+
lib.argumentChecks["format"][1].formatstr = true;
818+
check(code, false, false, Settings::Unspecified, &lib);
819+
ASSERT_EQUALS("[test.cpp:2]: (error) format format string has 1 parameters but only 0 are given.\n", errout.str());
820+
}
800821
};
801822

802823
REGISTER_TEST(TestIO)

test/testnullpointer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,7 +2116,7 @@ class TestNullPointer : public TestFixture {
21162116
// nothing bad..
21172117
{
21182118
Library library;
2119-
Library::ArgumentChecks arg = {false, false};
2119+
Library::ArgumentChecks arg;
21202120
library.argumentChecks["x"][1] = arg;
21212121
library.argumentChecks["x"][2] = arg;
21222122

@@ -2130,7 +2130,7 @@ class TestNullPointer : public TestFixture {
21302130
// for 1st parameter null pointer is not ok..
21312131
{
21322132
Library library;
2133-
struct Library::ArgumentChecks arg = {false, false};
2133+
struct Library::ArgumentChecks arg;
21342134
library.argumentChecks["x"][1] = arg;
21352135
library.argumentChecks["x"][2] = arg;
21362136
library.argumentChecks["x"][1].notnull = true;
@@ -2146,7 +2146,7 @@ class TestNullPointer : public TestFixture {
21462146
// for 2nd parameter uninit data is not ok..
21472147
{
21482148
Library library;
2149-
Library::ArgumentChecks arg = {false, false};
2149+
Library::ArgumentChecks arg;
21502150
library.argumentChecks["x"][1] = arg;
21512151
library.argumentChecks["x"][2] = arg;
21522152
library.argumentChecks["x"][2].notuninit = true;

0 commit comments

Comments
 (0)