Skip to content

Commit b691479

Browse files
committed
utils.h: reject preceding non-digits in strToInt()
1 parent b5ea328 commit b691479

5 files changed

Lines changed: 67 additions & 57 deletions

File tree

lib/utils.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ bool strToInt(const std::string& str, T &num, std::string* err = nullptr)
220220
tmp = std::stoll(str, &idx);
221221
if (idx != str.size()) {
222222
if (err)
223-
*err = "not an integer";
223+
*err = "not an integer (pos)";
224224
return false;
225225
}
226226
} catch (const std::out_of_range&) {
@@ -229,14 +229,19 @@ bool strToInt(const std::string& str, T &num, std::string* err = nullptr)
229229
return false;
230230
} catch (const std::invalid_argument &) {
231231
if (err)
232-
*err = "not an integer";
232+
*err = "not an integer (invalid_argument)";
233233
return false;
234234
}
235235
if (str.front() == '-' && std::numeric_limits<T>::min() == 0) {
236236
if (err)
237237
*err = "needs to be positive";
238238
return false;
239239
}
240+
if (str.front() != '+' && str.front() != '-' && !isdigit(str.front())) {
241+
if (err)
242+
*err = "not an integer";
243+
return false;
244+
}
240245
if (tmp < std::numeric_limits<T>::min() || tmp > std::numeric_limits<T>::max()) {
241246
if (err)
242247
*err = "out of range (limits)";
@@ -255,7 +260,7 @@ bool strToInt(const std::string& str, T &num, std::string* err = nullptr)
255260
tmp = std::stoull(str, &idx);
256261
if (idx != str.size()) {
257262
if (err)
258-
*err = "not an integer";
263+
*err = "not an integer (pos)";
259264
return false;
260265
}
261266
} catch (const std::out_of_range&) {
@@ -264,14 +269,19 @@ bool strToInt(const std::string& str, T &num, std::string* err = nullptr)
264269
return false;
265270
} catch (const std::invalid_argument &) {
266271
if (err)
267-
*err = "not an integer";
272+
*err = "not an integer (invalid_argument)";
268273
return false;
269274
}
270275
if (str.front() == '-') {
271276
if (err)
272277
*err = "needs to be positive";
273278
return false;
274279
}
280+
if (str.front() != '+' && !isdigit(str.front())) {
281+
if (err)
282+
*err = "not an integer";
283+
return false;
284+
}
275285
if (tmp > std::numeric_limits<T>::max()) {
276286
if (err)
277287
*err = "out of range (limits)";

test/testcmdlineparser.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,15 +1236,15 @@ class TestCmdlineParser : public TestFixture {
12361236
const char * const argv[] = {"cppcheck", "--error-exitcode=", "file.cpp"};
12371237
// Fails since exit code not given
12381238
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
1239-
ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str());
1239+
ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer (invalid_argument).\n", logger->str());
12401240
}
12411241

12421242
void errorExitcodeStr() {
12431243
REDIRECT;
12441244
const char * const argv[] = {"cppcheck", "--error-exitcode=foo", "file.cpp"};
12451245
// Fails since invalid exit code
12461246
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
1247-
ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer.\n", logger->str());
1247+
ASSERT_EQUALS("cppcheck: error: argument to '--error-exitcode=' is not valid - not an integer (invalid_argument).\n", logger->str());
12481248
}
12491249

12501250
void exitcodeSuppressionsOld() {
@@ -1395,15 +1395,15 @@ class TestCmdlineParser : public TestFixture {
13951395
const char * const argv[] = {"cppcheck", "-j", "file.cpp"};
13961396
// Fails since -j is missing thread count
13971397
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
1398-
ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str());
1398+
ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer (invalid_argument).\n", logger->str());
13991399
}
14001400

14011401
void jobsInvalid() {
14021402
REDIRECT;
14031403
const char * const argv[] = {"cppcheck", "-j", "e", "file.cpp"};
14041404
// Fails since invalid count given for -j
14051405
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
1406-
ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer.\n", logger->str());
1406+
ASSERT_EQUALS("cppcheck: error: argument to '-j' is not valid - not an integer (invalid_argument).\n", logger->str());
14071407
}
14081408

14091409
void jobsNoJobs() {
@@ -1433,15 +1433,15 @@ class TestCmdlineParser : public TestFixture {
14331433
const char * const argv[] = {"cppcheck", "--max-configs=", "file.cpp"};
14341434
// Fails since --max-configs= is missing limit
14351435
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
1436-
ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str());
1436+
ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer (invalid_argument).\n", logger->str());
14371437
}
14381438

14391439
void maxConfigsInvalid() {
14401440
REDIRECT;
14411441
const char * const argv[] = {"cppcheck", "--max-configs=e", "file.cpp"};
14421442
// Fails since invalid count given for --max-configs=
14431443
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
1444-
ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer.\n", logger->str());
1444+
ASSERT_EQUALS("cppcheck: error: argument to '--max-configs=' is not valid - not an integer (invalid_argument).\n", logger->str());
14451445
}
14461446

14471447
void maxConfigsTooSmall() {
@@ -1672,7 +1672,7 @@ class TestCmdlineParser : public TestFixture {
16721672
REDIRECT;
16731673
const char * const argv[] = {"cppcheck", "--report-progress=", "file.cpp"};
16741674
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
1675-
ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' is not valid - not an integer.\n", logger->str());
1675+
ASSERT_EQUALS("cppcheck: error: argument to '--report-progress=' is not valid - not an integer (invalid_argument).\n", logger->str());
16761676
}
16771677

16781678
void reportProgress3() {
@@ -2172,7 +2172,7 @@ class TestCmdlineParser : public TestFixture {
21722172
const char * const argv[] = {"cppcheck", "--xml", "--xml-version=a", "file.cpp"};
21732173
// FAils since unknown XML format version
21742174
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2175-
ASSERT_EQUALS("cppcheck: error: argument to '--xml-version=' is not valid - not an integer.\n", logger->str());
2175+
ASSERT_EQUALS("cppcheck: error: argument to '--xml-version=' is not valid - not an integer (invalid_argument).\n", logger->str());
21762176
}
21772177

21782178
void doc() {
@@ -2395,7 +2395,7 @@ class TestCmdlineParser : public TestFixture {
23952395
REDIRECT;
23962396
const char * const argv[] = {"cppcheck", "--valueflow-max-iterations=seven"};
23972397
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2398-
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - not an integer.\n", logger->str());
2398+
ASSERT_EQUALS("cppcheck: error: argument to '--valueflow-max-iterations=' is not valid - not an integer (invalid_argument).\n", logger->str());
23992399
}
24002400

24012401
void valueFlowMaxIterationsInvalid3() {
@@ -2423,7 +2423,7 @@ class TestCmdlineParser : public TestFixture {
24232423
REDIRECT;
24242424
const char * const argv[] = {"cppcheck", "--checks-max-time=one", "file.cpp"};
24252425
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2426-
ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' is not valid - not an integer.\n", logger->str());
2426+
ASSERT_EQUALS("cppcheck: error: argument to '--checks-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str());
24272427
}
24282428

24292429
#ifdef HAS_THREADING_MODEL_FORK
@@ -2445,7 +2445,7 @@ class TestCmdlineParser : public TestFixture {
24452445
REDIRECT;
24462446
const char * const argv[] = {"cppcheck", "-l", "one", "file.cpp"};
24472447
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2448-
ASSERT_EQUALS("cppcheck: error: argument to '-l' is not valid - not an integer.\n", logger->str());
2448+
ASSERT_EQUALS("cppcheck: error: argument to '-l' is not valid - not an integer (invalid_argument).\n", logger->str());
24492449
}
24502450
#else
24512451
void loadAverageNotSupported() {
@@ -2482,7 +2482,7 @@ class TestCmdlineParser : public TestFixture {
24822482
REDIRECT;
24832483
const char * const argv[] = {"cppcheck", "--max-ctu-depth=one", "file.cpp"};
24842484
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2485-
ASSERT_EQUALS("cppcheck: error: argument to '--max-ctu-depth=' is not valid - not an integer.\n", logger->str());
2485+
ASSERT_EQUALS("cppcheck: error: argument to '--max-ctu-depth=' is not valid - not an integer (invalid_argument).\n", logger->str());
24862486
}
24872487

24882488
void performanceValueflowMaxTime() {
@@ -2496,7 +2496,7 @@ class TestCmdlineParser : public TestFixture {
24962496
REDIRECT;
24972497
const char * const argv[] = {"cppcheck", "--performance-valueflow-max-time=one", "file.cpp"};
24982498
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2499-
ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-time=' is not valid - not an integer.\n", logger->str());
2499+
ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str());
25002500
}
25012501

25022502
void performanceValueFlowMaxIfCount() {
@@ -2510,7 +2510,7 @@ class TestCmdlineParser : public TestFixture {
25102510
REDIRECT;
25112511
const char * const argv[] = {"cppcheck", "--performance-valueflow-max-if-count=one", "file.cpp"};
25122512
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2513-
ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-if-count=' is not valid - not an integer.\n", logger->str());
2513+
ASSERT_EQUALS("cppcheck: error: argument to '--performance-valueflow-max-if-count=' is not valid - not an integer (invalid_argument).\n", logger->str());
25142514
}
25152515

25162516
void templateMaxTime() {
@@ -2524,7 +2524,7 @@ class TestCmdlineParser : public TestFixture {
25242524
REDIRECT;
25252525
const char * const argv[] = {"cppcheck", "--template-max-time=one", "file.cpp"};
25262526
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2527-
ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - not an integer.\n", logger->str());
2527+
ASSERT_EQUALS("cppcheck: error: argument to '--template-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str());
25282528
}
25292529

25302530
void templateMaxTimeInvalid2() {
@@ -2545,7 +2545,7 @@ class TestCmdlineParser : public TestFixture {
25452545
REDIRECT;
25462546
const char * const argv[] = {"cppcheck", "--typedef-max-time=one", "file.cpp"};
25472547
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
2548-
ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - not an integer.\n", logger->str());
2548+
ASSERT_EQUALS("cppcheck: error: argument to '--typedef-max-time=' is not valid - not an integer (invalid_argument).\n", logger->str());
25492549
}
25502550

25512551
void typedefMaxTimeInvalid2() {
@@ -3235,7 +3235,7 @@ class TestCmdlineParser : public TestFixture {
32353235
REDIRECT;
32363236
const char * const argv[] = {"cppcheck", "--max-template-recursion=", "file.cpp"};
32373237
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parseFromArgs(argv));
3238-
ASSERT_EQUALS("cppcheck: error: argument to '--max-template-recursion=' is not valid - not an integer.\n", logger->str());
3238+
ASSERT_EQUALS("cppcheck: error: argument to '--max-template-recursion=' is not valid - not an integer (invalid_argument).\n", logger->str());
32393239
}
32403240

32413241
void emitDuplicates() {

test/testerrorlogger.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ class TestErrorLogger : public TestFixture {
599599
"0 "
600600
"0 ";
601601
ErrorMessage msg;
602-
ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid CWE ID - not an integer");
602+
ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid CWE ID - not an integer (invalid_argument)");
603603
}
604604
{
605605
// invalid hash
@@ -615,7 +615,7 @@ class TestErrorLogger : public TestFixture {
615615
"0 "
616616
"0 ";
617617
ErrorMessage msg;
618-
ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid hash - not an integer");
618+
ASSERT_THROW_INTERNAL_EQUALS(msg.deserialize(str), INTERNAL, "Internal Error: Deserialization of error message failed - invalid hash - not an integer (invalid_argument)");
619619
}
620620
{
621621
// out-of-range CWE ID

test/testsuppressions.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,12 @@ class TestSuppressions : public TestFixture {
188188
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id::1"), std::runtime_error, "filename is missing");
189189

190190
// missing/invalid line
191-
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer)");
192-
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:\n"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer)");
193-
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:\n1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer)");
194-
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:#1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer)"); // TODO: looks like a valid filename
195-
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c://1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer)");
196-
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:zero"), std::runtime_error, "invalid line number (converting 'zero' to integer failed - not an integer)");
191+
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))");
192+
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:\n"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))");
193+
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:\n1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))");
194+
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:#1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))"); // TODO: looks like a valid filename
195+
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c://1"), std::runtime_error, "invalid line number (converting '' to integer failed - not an integer (invalid_argument))");
196+
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:zero"), std::runtime_error, "invalid line number (converting 'zero' to integer failed - not an integer (invalid_argument))");
197197

198198
// invalid extras
199199
ASSERT_THROW_EQUALS(SuppressionList::parseLine("id:1.c:1\n"), std::runtime_error, "unexpected extra ''");

0 commit comments

Comments
 (0)