Fixed #2200 (MathLib: Calculation overflow)
This commit is contained in:
parent
9ccc57a455
commit
e8ca76e02e
|
@ -605,7 +605,7 @@ private:
|
||||||
if (Token::Match(tok.tokAt(6), "%num% )"))
|
if (Token::Match(tok.tokAt(6), "%num% )"))
|
||||||
{
|
{
|
||||||
const unsigned int len = Token::getStrLength(tok.tokAt(4));
|
const unsigned int len = Token::getStrLength(tok.tokAt(4));
|
||||||
const long sz = MathLib::toLongNumber(tok.strAt(6));
|
const MathLib::bigint sz = MathLib::toLongNumber(tok.strAt(6));
|
||||||
if (sz >= 0 && len >= static_cast<unsigned long>(sz))
|
if (sz >= 0 && len >= static_cast<unsigned long>(sz))
|
||||||
{
|
{
|
||||||
init_strncpy(checks, tok.tokAt(2));
|
init_strncpy(checks, tok.tokAt(2));
|
||||||
|
|
|
@ -30,23 +30,37 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
|
||||||
long MathLib::toLongNumber(const std::string &str)
|
MathLib::bigint MathLib::toLongNumber(const std::string &str)
|
||||||
{
|
{
|
||||||
|
// hexadecimal numbers:
|
||||||
if (str.compare(0, 2, "0x") == 0
|
if (str.compare(0, 2, "0x") == 0
|
||||||
|| str.compare(0, 3, "+0x") == 0
|
|| str.compare(0, 3, "+0x") == 0
|
||||||
|| str.compare(0, 3, "-0x") == 0)
|
|| str.compare(0, 3, "-0x") == 0)
|
||||||
{
|
{
|
||||||
return std::strtol(str.c_str(), '\0', 16);
|
bigint ret = 0;
|
||||||
|
std::istringstream istr(str.substr((str[0]=='0') ? 2 : 3));
|
||||||
|
istr >> std::hex >> ret;
|
||||||
|
return (str[0]=='-') ? -ret : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// octal numbers:
|
||||||
if (str.compare(0, 1, "0") == 0
|
if (str.compare(0, 1, "0") == 0
|
||||||
|| str.compare(0, 2, "+0") == 0
|
|| str.compare(0, 2, "+0") == 0
|
||||||
|| str.compare(0, 2, "-0") == 0)
|
|| str.compare(0, 2, "-0") == 0)
|
||||||
{
|
{
|
||||||
return std::strtol(str.c_str(), '\0', 8);
|
bigint ret = 0;
|
||||||
|
std::istringstream istr(str.substr((str[0]=='0') ? 1 : 2));
|
||||||
|
istr >> std::oct >> ret;
|
||||||
|
return (str[0]=='-') ? -ret : ret;
|
||||||
}
|
}
|
||||||
return (str.find("E", 0) != std::string::npos || str.find("e", 0) != std::string::npos)
|
|
||||||
? static_cast<long>(std::atof(str.c_str()))
|
if (str.find_first_of("eE") != std::string::npos)
|
||||||
: std::atol(str.c_str());
|
return static_cast<bigint>(std::atof(str.c_str()));
|
||||||
|
|
||||||
|
bigint ret = 0;
|
||||||
|
std::istringstream istr(str);
|
||||||
|
istr >> ret;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MathLib::toDoubleNumber(const std::string &str)
|
double MathLib::toDoubleNumber(const std::string &str)
|
||||||
|
@ -199,7 +213,7 @@ std::string MathLib::add(const std::string & first, const std::string & second)
|
||||||
{
|
{
|
||||||
if (MathLib::isInt(first) && MathLib::isInt(second))
|
if (MathLib::isInt(first) && MathLib::isInt(second))
|
||||||
{
|
{
|
||||||
return toString<long>(toLongNumber(first) + toLongNumber(second));
|
return toString<bigint>(toLongNumber(first) + toLongNumber(second));
|
||||||
}
|
}
|
||||||
return toString<double>(toDoubleNumber(first) + toDoubleNumber(second));
|
return toString<double>(toDoubleNumber(first) + toDoubleNumber(second));
|
||||||
}
|
}
|
||||||
|
@ -208,7 +222,7 @@ std::string MathLib::subtract(const std::string &first, const std::string &secon
|
||||||
{
|
{
|
||||||
if (MathLib::isInt(first) && MathLib::isInt(second))
|
if (MathLib::isInt(first) && MathLib::isInt(second))
|
||||||
{
|
{
|
||||||
return toString<long>(toLongNumber(first) - toLongNumber(second));
|
return toString<bigint>(toLongNumber(first) - toLongNumber(second));
|
||||||
}
|
}
|
||||||
return toString<double>(toDoubleNumber(first) - toDoubleNumber(second));
|
return toString<double>(toDoubleNumber(first) - toDoubleNumber(second));
|
||||||
}
|
}
|
||||||
|
@ -217,7 +231,7 @@ std::string MathLib::divide(const std::string &first, const std::string &second)
|
||||||
{
|
{
|
||||||
if (MathLib::isInt(first) && MathLib::isInt(second))
|
if (MathLib::isInt(first) && MathLib::isInt(second))
|
||||||
{
|
{
|
||||||
return toString<long>(toLongNumber(first) / toLongNumber(second));
|
return toString<bigint>(toLongNumber(first) / toLongNumber(second));
|
||||||
}
|
}
|
||||||
return toString<double>(toDoubleNumber(first) / toDoubleNumber(second));
|
return toString<double>(toDoubleNumber(first) / toDoubleNumber(second));
|
||||||
}
|
}
|
||||||
|
@ -226,7 +240,7 @@ std::string MathLib::multiply(const std::string &first, const std::string &secon
|
||||||
{
|
{
|
||||||
if (MathLib::isInt(first) && MathLib::isInt(second))
|
if (MathLib::isInt(first) && MathLib::isInt(second))
|
||||||
{
|
{
|
||||||
return toString<long>(toLongNumber(first) * toLongNumber(second));
|
return toString<bigint>(toLongNumber(first) * toLongNumber(second));
|
||||||
}
|
}
|
||||||
return toString<double>(toDoubleNumber(first) * toDoubleNumber(second));
|
return toString<double>(toDoubleNumber(first) * toDoubleNumber(second));
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,16 @@ class Tokenizer;
|
||||||
class MathLib
|
class MathLib
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static long toLongNumber(const std::string & str);
|
// To compile Cppcheck on a compiler that doesn't support "long long",
|
||||||
|
// use NOLONGLONG.
|
||||||
|
#ifdef NOLONGLONG
|
||||||
|
typedef long bigint;
|
||||||
|
#else
|
||||||
|
typedef long long bigint;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static bigint toLongNumber(const std::string & str);
|
||||||
static double toDoubleNumber(const std::string & str);
|
static double toDoubleNumber(const std::string & str);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -6571,9 +6571,9 @@ bool Tokenizer::simplifyCalculations()
|
||||||
const std::string after(tok->tokAt(3) ? tok->strAt(3).c_str() : "");
|
const std::string after(tok->tokAt(3) ? tok->strAt(3).c_str() : "");
|
||||||
if ((prev == "(" || prev == "&&" || prev == "||") && (after == ")" || after == "&&" || after == "||"))
|
if ((prev == "(" || prev == "&&" || prev == "||") && (after == ")" || after == "&&" || after == "||"))
|
||||||
{
|
{
|
||||||
const int op1(MathLib::toLongNumber(tok->str()));
|
const MathLib::bigint op1(MathLib::toLongNumber(tok->str()));
|
||||||
const std::string &cmp(tok->next()->str());
|
const std::string &cmp(tok->next()->str());
|
||||||
const int op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
const MathLib::bigint op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
|
|
||||||
|
@ -6598,16 +6598,16 @@ bool Tokenizer::simplifyCalculations()
|
||||||
|
|
||||||
if (Token::Match(tok->previous(), "[([,=] %num% <<|>> %num%"))
|
if (Token::Match(tok->previous(), "[([,=] %num% <<|>> %num%"))
|
||||||
{
|
{
|
||||||
const int op1(MathLib::toLongNumber(tok->str()));
|
const MathLib::bigint op1(MathLib::toLongNumber(tok->str()));
|
||||||
const int op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
const MathLib::bigint op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
||||||
int result;
|
MathLib::bigint result;
|
||||||
|
|
||||||
if (tok->next()->str() == "<<")
|
if (tok->next()->str() == "<<")
|
||||||
result = op1 << op2;
|
result = op1 << op2;
|
||||||
else
|
else
|
||||||
result = op1 >> op2;
|
result = op1 >> op2;
|
||||||
|
|
||||||
std::stringstream ss;
|
std::ostringstream ss;
|
||||||
ss << result;
|
ss << result;
|
||||||
|
|
||||||
tok->str(ss.str());
|
tok->str(ss.str());
|
||||||
|
@ -7091,7 +7091,7 @@ void Tokenizer::simplifyEnum()
|
||||||
|
|
||||||
end = tok1->tokAt(-1)->link();
|
end = tok1->tokAt(-1)->link();
|
||||||
|
|
||||||
long lastValue = -1;
|
MathLib::bigint lastValue = -1;
|
||||||
Token * lastEnumValueStart = 0;
|
Token * lastEnumValueStart = 0;
|
||||||
Token * lastEnumValueEnd = 0;
|
Token * lastEnumValueEnd = 0;
|
||||||
|
|
||||||
|
@ -7146,7 +7146,7 @@ void Tokenizer::simplifyEnum()
|
||||||
// value is previous expression + 1
|
// value is previous expression + 1
|
||||||
tok1->insertToken("+");
|
tok1->insertToken("+");
|
||||||
tok1 = tok1->next();
|
tok1 = tok1->next();
|
||||||
tok1->insertToken(MathLib::toString<long>(lastValue));
|
tok1->insertToken(MathLib::toString<MathLib::bigint>(lastValue));
|
||||||
enumValue = 0;
|
enumValue = 0;
|
||||||
enumValueStart = valueStart->next();
|
enumValueStart = valueStart->next();
|
||||||
enumValueEnd = tok1->next();
|
enumValueEnd = tok1->next();
|
||||||
|
@ -7154,7 +7154,7 @@ void Tokenizer::simplifyEnum()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// value is previous numeric value + 1
|
// value is previous numeric value + 1
|
||||||
tok1->insertToken(MathLib::toString<long>(lastValue));
|
tok1->insertToken(MathLib::toString<MathLib::bigint>(lastValue));
|
||||||
enumValue = tok1->next();
|
enumValue = tok1->next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@ private:
|
||||||
ASSERT_EQUALS("-3000" , MathLib::multiply("-1.0E+3", "3"));
|
ASSERT_EQUALS("-3000" , MathLib::multiply("-1.0E+3", "3"));
|
||||||
ASSERT_EQUALS("0" , MathLib::multiply("-1.0E+3", "0"));
|
ASSERT_EQUALS("0" , MathLib::multiply("-1.0E+3", "0"));
|
||||||
ASSERT_EQUALS("0" , MathLib::multiply("+1.0E+3", "0"));
|
ASSERT_EQUALS("0" , MathLib::multiply("+1.0E+3", "0"));
|
||||||
TODO_ASSERT_EQUALS("2147483648" , MathLib::multiply("2","1073741824"));
|
ASSERT_EQUALS("2147483648" , MathLib::multiply("2","1073741824"));
|
||||||
ASSERT_EQUALS("536870912" , MathLib::multiply("512","1048576"));
|
ASSERT_EQUALS("536870912" , MathLib::multiply("512","1048576"));
|
||||||
|
|
||||||
// divide
|
// divide
|
||||||
|
|
Loading…
Reference in New Issue