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% )"))
|
||||
{
|
||||
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))
|
||||
{
|
||||
init_strncpy(checks, tok.tokAt(2));
|
||||
|
|
|
@ -30,23 +30,37 @@
|
|||
#include <cmath>
|
||||
#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
|
||||
|| 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
|
||||
|| 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()))
|
||||
: std::atol(str.c_str());
|
||||
|
||||
if (str.find_first_of("eE") != std::string::npos)
|
||||
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)
|
||||
|
@ -199,7 +213,7 @@ std::string MathLib::add(const std::string & first, const std::string & 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));
|
||||
}
|
||||
|
@ -208,7 +222,7 @@ std::string MathLib::subtract(const std::string &first, const std::string &secon
|
|||
{
|
||||
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));
|
||||
}
|
||||
|
@ -217,7 +231,7 @@ std::string MathLib::divide(const std::string &first, const std::string &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));
|
||||
}
|
||||
|
@ -226,7 +240,7 @@ std::string MathLib::multiply(const std::string &first, const std::string &secon
|
|||
{
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -33,7 +33,16 @@ class Tokenizer;
|
|||
class MathLib
|
||||
{
|
||||
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);
|
||||
|
||||
template<typename T>
|
||||
|
|
|
@ -6571,9 +6571,9 @@ bool Tokenizer::simplifyCalculations()
|
|||
const std::string after(tok->tokAt(3) ? tok->strAt(3).c_str() : "");
|
||||
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 int op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
||||
const MathLib::bigint op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
||||
|
||||
std::string result;
|
||||
|
||||
|
@ -6598,16 +6598,16 @@ bool Tokenizer::simplifyCalculations()
|
|||
|
||||
if (Token::Match(tok->previous(), "[([,=] %num% <<|>> %num%"))
|
||||
{
|
||||
const int op1(MathLib::toLongNumber(tok->str()));
|
||||
const int op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
||||
int result;
|
||||
const MathLib::bigint op1(MathLib::toLongNumber(tok->str()));
|
||||
const MathLib::bigint op2(MathLib::toLongNumber(tok->tokAt(2)->str()));
|
||||
MathLib::bigint result;
|
||||
|
||||
if (tok->next()->str() == "<<")
|
||||
result = op1 << op2;
|
||||
else
|
||||
result = op1 >> op2;
|
||||
|
||||
std::stringstream ss;
|
||||
std::ostringstream ss;
|
||||
ss << result;
|
||||
|
||||
tok->str(ss.str());
|
||||
|
@ -7091,7 +7091,7 @@ void Tokenizer::simplifyEnum()
|
|||
|
||||
end = tok1->tokAt(-1)->link();
|
||||
|
||||
long lastValue = -1;
|
||||
MathLib::bigint lastValue = -1;
|
||||
Token * lastEnumValueStart = 0;
|
||||
Token * lastEnumValueEnd = 0;
|
||||
|
||||
|
@ -7146,7 +7146,7 @@ void Tokenizer::simplifyEnum()
|
|||
// value is previous expression + 1
|
||||
tok1->insertToken("+");
|
||||
tok1 = tok1->next();
|
||||
tok1->insertToken(MathLib::toString<long>(lastValue));
|
||||
tok1->insertToken(MathLib::toString<MathLib::bigint>(lastValue));
|
||||
enumValue = 0;
|
||||
enumValueStart = valueStart->next();
|
||||
enumValueEnd = tok1->next();
|
||||
|
@ -7154,7 +7154,7 @@ void Tokenizer::simplifyEnum()
|
|||
else
|
||||
{
|
||||
// value is previous numeric value + 1
|
||||
tok1->insertToken(MathLib::toString<long>(lastValue));
|
||||
tok1->insertToken(MathLib::toString<MathLib::bigint>(lastValue));
|
||||
enumValue = tok1->next();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ private:
|
|||
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"));
|
||||
TODO_ASSERT_EQUALS("2147483648" , MathLib::multiply("2","1073741824"));
|
||||
ASSERT_EQUALS("2147483648" , MathLib::multiply("2","1073741824"));
|
||||
ASSERT_EQUALS("536870912" , MathLib::multiply("512","1048576"));
|
||||
|
||||
// divide
|
||||
|
|
Loading…
Reference in New Issue