Skip to content

Commit 64faa78

Browse files
committed
Fixed danmar#4087 (div by zero check is invalid for floats)
1 parent 1863306 commit 64faa78

File tree

6 files changed

+108
-98
lines changed

6 files changed

+108
-98
lines changed

lib/checkbufferoverrun.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ static bool for_condition(const Token *tok2, unsigned int varid, std::string &mi
295295
Token::Match(tok2, "%varid% != %num% ; %varid% ++", varid)) {
296296
maxMinFlipped = false;
297297
const MathLib::bigint value = MathLib::toLongNumber(tok2->strAt(2));
298-
max_value = MathLib::toString<MathLib::bigint>(value - 1);
298+
max_value = MathLib::longToString(value - 1);
299299
} else if (Token::Match(tok2, "%varid% <= %num% ;|&&|%oror%", varid)) {
300300
maxMinFlipped = false;
301301
max_value = tok2->strAt(2);
@@ -305,7 +305,7 @@ static bool for_condition(const Token *tok2, unsigned int varid, std::string &mi
305305
maxMinFlipped = true;
306306
const MathLib::bigint value = MathLib::toLongNumber(tok2->str());
307307
max_value = min_value;
308-
min_value = MathLib::toString<MathLib::bigint>(value + 1);
308+
min_value = MathLib::longToString(value + 1);
309309
} else if (Token::Match(tok2, "%num% <= %varid% ;|&&|%oror%", varid)) {
310310
maxMinFlipped = true;
311311
max_value = min_value;
@@ -351,7 +351,7 @@ static bool for_maxvalue(const Token * const stepvalue, const std::string &min_v
351351
MathLib::bigint max = MathLib::toLongNumber(max_value);
352352
const MathLib::bigint min = MathLib::toLongNumber(min_value);
353353
max = ((max - min) / num) * num + min;
354-
max_value = MathLib::toString<MathLib::bigint>(max);
354+
max_value = MathLib::longToString(max);
355355
return true;
356356
}
357357

lib/mathlib.cpp

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ MathLib::bigint MathLib::toLongNumber(const std::string &str)
6767
return ret;
6868
}
6969

70+
std::string MathLib::longToString(const bigint value)
71+
{
72+
std::ostringstream result;
73+
result << value;
74+
return result.str();
75+
}
76+
7077
double MathLib::toDoubleNumber(const std::string &str)
7178
{
7279
if (isHex(str))
@@ -81,6 +88,18 @@ double MathLib::toDoubleNumber(const std::string &str)
8188
return ret;
8289
}
8390

91+
std::string MathLib::doubleToString(const double value)
92+
{
93+
std::ostringstream result;
94+
result.precision(12);
95+
result << value;
96+
if (result.str() == "-0")
97+
return "0.0";
98+
if (result.str().find(".") == std::string::npos)
99+
return result.str() + ".0";
100+
return result.str();
101+
}
102+
84103
bool MathLib::isFloat(const std::string &s)
85104
{
86105
// every number that contains a . is a float
@@ -215,25 +234,25 @@ bool MathLib::isInt(const std::string & s)
215234
std::string MathLib::add(const std::string & first, const std::string & second)
216235
{
217236
if (MathLib::isInt(first) && MathLib::isInt(second)) {
218-
return toString<bigint>(toLongNumber(first) + toLongNumber(second));
237+
return longToString(toLongNumber(first) + toLongNumber(second));
219238
}
220239

221240
double d1 = toDoubleNumber(first);
222241
double d2 = toDoubleNumber(second);
223242

224243
int count = 0;
225-
while (d1 > 100000.0 * d2 && toString<double>(d1+d2)==first && ++count<5)
244+
while (d1 > 100000.0 * d2 && doubleToString(d1+d2)==first && ++count<5)
226245
d2 *= 10.0;
227-
while (d2 > 100000.0 * d1 && toString<double>(d1+d2)==second && ++count<5)
246+
while (d2 > 100000.0 * d1 && doubleToString(d1+d2)==second && ++count<5)
228247
d1 *= 10.0;
229248

230-
return toString<double>(d1 + d2);
249+
return doubleToString(d1 + d2);
231250
}
232251

233252
std::string MathLib::subtract(const std::string &first, const std::string &second)
234253
{
235254
if (MathLib::isInt(first) && MathLib::isInt(second)) {
236-
return toString<bigint>(toLongNumber(first) - toLongNumber(second));
255+
return longToString(toLongNumber(first) - toLongNumber(second));
237256
}
238257

239258
if (first == second)
@@ -243,12 +262,12 @@ std::string MathLib::subtract(const std::string &first, const std::string &secon
243262
double d2 = toDoubleNumber(second);
244263

245264
int count = 0;
246-
while (d1 > 100000.0 * d2 && toString<double>(d1-d2)==first && ++count<5)
265+
while (d1 > 100000.0 * d2 && doubleToString(d1-d2)==first && ++count<5)
247266
d2 *= 10.0;
248-
while (d2 > 100000.0 * d1 && toString<double>(d1-d2)==second && ++count<5)
267+
while (d2 > 100000.0 * d1 && doubleToString(d1-d2)==second && ++count<5)
249268
d1 *= 10.0;
250269

251-
return toString<double>(d1 - d2);
270+
return doubleToString(d1 - d2);
252271
}
253272

254273
std::string MathLib::divide(const std::string &first, const std::string &second)
@@ -257,17 +276,17 @@ std::string MathLib::divide(const std::string &first, const std::string &second)
257276
bigint b = toLongNumber(second);
258277
if (b == 0)
259278
throw InternalError(0, "Internal Error: Division by zero");
260-
return toString<bigint>(toLongNumber(first) / b);
279+
return longToString(toLongNumber(first) / b);
261280
}
262-
return toString<double>(toDoubleNumber(first) / toDoubleNumber(second));
281+
return doubleToString(toDoubleNumber(first) / toDoubleNumber(second));
263282
}
264283

265284
std::string MathLib::multiply(const std::string &first, const std::string &second)
266285
{
267286
if (MathLib::isInt(first) && MathLib::isInt(second)) {
268-
return toString<bigint>(toLongNumber(first) * toLongNumber(second));
287+
return longToString(toLongNumber(first) * toLongNumber(second));
269288
}
270-
return toString<double>(toDoubleNumber(first) * toDoubleNumber(second));
289+
return doubleToString(toDoubleNumber(first) * toDoubleNumber(second));
271290
}
272291

273292
std::string MathLib::mod(const std::string &first, const std::string &second)
@@ -276,9 +295,9 @@ std::string MathLib::mod(const std::string &first, const std::string &second)
276295
bigint b = toLongNumber(second);
277296
if (b == 0)
278297
throw InternalError(0, "Internal Error: Division by zero");
279-
return toString<MathLib::bigint>(toLongNumber(first) % b);
298+
return longToString(toLongNumber(first) % b);
280299
}
281-
return toString<double>(fmod(toDoubleNumber(first),toDoubleNumber(second)));
300+
return doubleToString(fmod(toDoubleNumber(first),toDoubleNumber(second)));
282301
}
283302

284303
std::string MathLib::calculate(const std::string &first, const std::string &second, char action)
@@ -300,13 +319,13 @@ std::string MathLib::calculate(const std::string &first, const std::string &seco
300319
return MathLib::mod(first, second);
301320

302321
case '&':
303-
return MathLib::toString(MathLib::toLongNumber(first) & MathLib::toLongNumber(second));
322+
return MathLib::longToString(MathLib::toLongNumber(first) & MathLib::toLongNumber(second));
304323

305324
case '|':
306-
return MathLib::toString(MathLib::toLongNumber(first) | MathLib::toLongNumber(second));
325+
return MathLib::longToString(MathLib::toLongNumber(first) | MathLib::toLongNumber(second));
307326

308327
case '^':
309-
return MathLib::toString(MathLib::toLongNumber(first) ^ MathLib::toLongNumber(second));
328+
return MathLib::longToString(MathLib::toLongNumber(first) ^ MathLib::toLongNumber(second));
310329

311330
default:
312331
throw InternalError(0, std::string("Unexpected action '") + action + "' in MathLib::calculate(). Please report this to Cppcheck developers.");
@@ -315,31 +334,31 @@ std::string MathLib::calculate(const std::string &first, const std::string &seco
315334

316335
std::string MathLib::sin(const std::string &tok)
317336
{
318-
return toString<double>(std::sin(toDoubleNumber(tok)));
337+
return doubleToString(std::sin(toDoubleNumber(tok)));
319338
}
320339

321340

322341
std::string MathLib::cos(const std::string &tok)
323342
{
324-
return toString<double>(std::cos(toDoubleNumber(tok)));
343+
return doubleToString(std::cos(toDoubleNumber(tok)));
325344
}
326345

327346
std::string MathLib::tan(const std::string &tok)
328347
{
329-
return toString<double>(std::tan(toDoubleNumber(tok)));
348+
return doubleToString(std::tan(toDoubleNumber(tok)));
330349
}
331350

332351

333352
std::string MathLib::abs(const std::string &tok)
334353
{
335-
return toString<double>(std::abs(toDoubleNumber(tok)));
354+
return doubleToString(std::abs(toDoubleNumber(tok)));
336355
}
337356

338357
bool MathLib::isEqual(const std::string &first, const std::string &second)
339358
{
340359
// this conversion is needed for formating
341360
// e.g. if first=0.1 and second=1.0E-1, the direct comparison of the strings whould fail
342-
return toString<double>(toDoubleNumber(first)) == toString<double>(toDoubleNumber(second));
361+
return doubleToString(toDoubleNumber(first)) == doubleToString(toDoubleNumber(second));
343362
}
344363

345364
bool MathLib::isNotEqual(const std::string &first, const std::string &second)

lib/mathlib.h

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,9 @@ class CPPCHECKLIB MathLib {
3434
typedef long long bigint;
3535

3636
static bigint toLongNumber(const std::string & str);
37+
static std::string longToString(const bigint value);
3738
static double toDoubleNumber(const std::string & str);
38-
39-
template<typename T>
40-
static std::string toString(const T &d) {
41-
std::ostringstream result;
42-
result.precision(8);
43-
result << d;
44-
if (isNullValue(result.str()))
45-
return std::string("0");
46-
return result.str();
47-
}
39+
static std::string doubleToString(const double value);
4840

4941
static bool isInt(const std::string & str);
5042
static bool isFloat(const std::string &str);

lib/templatesimplifier.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -744,9 +744,9 @@ bool TemplateSimplifier::simplifyNumericCalculations(Token *tok)
744744
result = MathLib::calculate(tok->str(), tok->strAt(2), cop);
745745
else if (cop == '<') {
746746
if (tok->previous()->str() != "<<" && rightInt > 0) // Ensure that its not a shift operator as used for streams
747-
result = MathLib::toString<MathLib::bigint>(leftInt << rightInt);
747+
result = MathLib::longToString(leftInt << rightInt);
748748
} else if (rightInt > 0)
749-
result = MathLib::toString<MathLib::bigint>(leftInt >> rightInt);
749+
result = MathLib::longToString(leftInt >> rightInt);
750750

751751
if (!result.empty()) {
752752
ret = true;
@@ -809,7 +809,7 @@ bool TemplateSimplifier::simplifyCalculations(Token *_tokens)
809809

810810
if (tok->type() == Token::eChar &&
811811
Token::Match(tok->previous(), "(|&&|%oror% %any% ==|!=|<=|<|>=|> %num% &&|%oror%|)")) {
812-
tok->str(MathLib::toString(tok->str()[1] & 0xff));
812+
tok->str(MathLib::longToString(tok->str()[1] & 0xff));
813813
}
814814

815815
if (tok->isNumber()) {

lib/tokenize.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ static Token *splitDefinitionFromTypedef(Token *tok)
399399
name = tok1->next()->str();
400400
else { // create a unique name
401401
static unsigned int count = 0;
402-
name = "Unnamed" + MathLib::toString<unsigned int>(count++);
402+
name = "Unnamed" + MathLib::longToString(count++);
403403
}
404404
tok->next()->insertToken(name);
405405
} else
@@ -2147,7 +2147,7 @@ void Tokenizer::simplifyLineMacro()
21472147
{
21482148
for (Token *tok = list.front(); tok; tok = tok->next()) {
21492149
if (tok->str() == "__LINE__")
2150-
tok->str(MathLib::toString(tok->linenr()));
2150+
tok->str(MathLib::longToString(tok->linenr()));
21512151
}
21522152
}
21532153

@@ -2402,7 +2402,7 @@ void Tokenizer::arraySize()
24022402
if (addlength || Token::Match(tok, "%var% [ ] = %str% ;")) {
24032403
tok = tok->next();
24042404
std::size_t sz = tok->strAt(3).length() - 1;
2405-
tok->insertToken(MathLib::toString<unsigned int>((unsigned int)sz));
2405+
tok->insertToken(MathLib::longToString((unsigned int)sz));
24062406
addlength = false;
24072407
tok = tok->tokAt(5);
24082408
}
@@ -2428,7 +2428,7 @@ void Tokenizer::arraySize()
24282428
}
24292429

24302430
if (sz != 0)
2431-
tok->insertToken(MathLib::toString<unsigned int>(sz));
2431+
tok->insertToken(MathLib::longToString(sz));
24322432

24332433
tok = end->next() ? end->next() : end;
24342434
}
@@ -2500,7 +2500,7 @@ void Tokenizer::simplifyTemplates()
25002500
Token * const tok3 = tok->next();
25012501
const unsigned int sizeOfResult = sizeOfType(tok3->tokAt(3));
25022502
tok3->deleteNext(4);
2503-
tok3->insertToken(MathLib::toString<unsigned int>(sizeOfResult));
2503+
tok3->insertToken(MathLib::longToString(sizeOfResult));
25042504
}
25052505
}
25062506

@@ -3057,7 +3057,7 @@ bool Tokenizer::simplifySizeof()
30573057
continue;
30583058
}
30593059

3060-
sizeOfVar[varId] = MathLib::toString<unsigned int>(size);
3060+
sizeOfVar[varId] = MathLib::longToString(size);
30613061
}
30623062

30633063
else if (Token::Match(tok->tokAt(-3), "[;{}(,] struct %type% %var% [;,)]")) {
@@ -3070,22 +3070,22 @@ bool Tokenizer::simplifySizeof()
30703070
if (size == 0)
30713071
continue;
30723072

3073-
sizeOfVar[varId] = MathLib::toString<unsigned long>(size * static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(2))));
3073+
sizeOfVar[varId] = MathLib::longToString(size * static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(2))));
30743074
}
30753075

30763076
else if (Token::Match(tok->previous(), "%type% %var% [ %num% ] [,)]") ||
30773077
Token::Match(tok->tokAt(-2), "%type% * %var% [ %num% ] [,)]")) {
30783078
Token tempTok(0);
30793079
tempTok.str("*");
3080-
sizeOfVar[varId] = MathLib::toString<unsigned long>(sizeOfType(&tempTok));
3080+
sizeOfVar[varId] = MathLib::longToString(sizeOfType(&tempTok));
30813081
}
30823082

30833083
else if (Token::Match(tok->previous(), "%type% %var% [ ] = %str% ;")) {
30843084
const unsigned int size = sizeOfType(tok->tokAt(4));
30853085
if (size == 0)
30863086
continue;
30873087

3088-
sizeOfVar[varId] = MathLib::toString<unsigned int>(size);
3088+
sizeOfVar[varId] = MathLib::longToString(size);
30893089
}
30903090
}
30913091
}
@@ -3216,7 +3216,7 @@ bool Tokenizer::simplifySizeof()
32163216
}
32173217

32183218
if (Token::simpleMatch(tok->next(), "( * )")) {
3219-
tok->str(MathLib::toString<unsigned long>(sizeOfType(tok->tokAt(2))));
3219+
tok->str(MathLib::longToString(sizeOfType(tok->tokAt(2))));
32203220
tok->deleteNext(3);
32213221
ret = true;
32223222
}
@@ -3238,7 +3238,7 @@ bool Tokenizer::simplifySizeof()
32383238
else if (Token::Match(tok, "sizeof ( %type% )")) {
32393239
unsigned int size = sizeOfType(tok->tokAt(2));
32403240
if (size > 0) {
3241-
tok->str(MathLib::toString<unsigned int>(size));
3241+
tok->str(MathLib::longToString(size));
32423242
tok->deleteNext(3);
32433243
ret = true;
32443244
}
@@ -3267,7 +3267,7 @@ bool Tokenizer::simplifySizeof()
32673267
}
32683268

32693269
if (sz > 0) {
3270-
tok->str(MathLib::toString<size_t>(sz));
3270+
tok->str(MathLib::longToString(sz));
32713271
Token::eraseTokens(tok, tok->next()->link()->next());
32723272
ret = true;
32733273
}
@@ -3885,7 +3885,7 @@ void Tokenizer::removeRedundantFor()
38853885
// get the correct end value
38863886
Token *tok2 = tok->next()->link();
38873887
tok2->insertToken(";");
3888-
tok2->insertToken(MathLib::toString(num2));
3888+
tok2->insertToken(MathLib::longToString(num2));
38893889
tok2->insertToken("=");
38903890
tok2->insertToken(varname);
38913891
tok2->next()->varId(varid);
@@ -6058,7 +6058,7 @@ bool Tokenizer::simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2,
60586058
value = tok2->strAt(6);
60596059
valueVarId = tok2->tokAt(6)->varId();
60606060
} else
6061-
value = MathLib::toString(MathLib::toLongNumber(tok2->strAt(6)) + 1);
6061+
value = MathLib::longToString(MathLib::toLongNumber(tok2->strAt(6)) + 1);
60626062

60636063
// Skip for-body..
60646064
tok3 = tok2->previous()->link()->next()->link()->next();
@@ -7199,7 +7199,7 @@ void Tokenizer::simplifyEnum()
71997199
enumValueEnd = tok1->next();
72007200
} else {
72017201
// value is previous numeric value + 1
7202-
tok1->insertToken(MathLib::toString<MathLib::bigint>(lastValue));
7202+
tok1->insertToken(MathLib::longToString(lastValue));
72037203
enumValue = tok1->next();
72047204
}
72057205
} else if (Token::Match(tok1->previous(), ",|{ %type% = %num% ,|}")) {
@@ -7816,7 +7816,7 @@ void Tokenizer::simplifyMathFunctions()
78167816
tok->deleteThis();
78177817

78187818
// Convert string into a number
7819-
tok->str(MathLib::toString(MathLib::toLongNumber(tok->strValue())));
7819+
tok->str(MathLib::longToString(MathLib::toLongNumber(tok->strValue())));
78207820

78217821
// Delete remaining )
78227822
tok->deleteNext();
@@ -8376,7 +8376,7 @@ void Tokenizer::simplifyStructDecl()
83768376
if (Token::Match(tok->next(), "*|&| %type% ,|;|[")) {
83778377
std::string name;
83788378

8379-
name = "Anonymous" + MathLib::toString<unsigned int>(count++);
8379+
name = "Anonymous" + MathLib::longToString(count++);
83808380

83818381
tok1->insertToken(name);
83828382

0 commit comments

Comments
 (0)