some MathLib adjustments for out-of-range numbers after std::stringstream removal (#3100)

This commit is contained in:
Oliver Stöneberg 2021-02-13 19:10:45 +01:00 committed by GitHub
parent 75e439e56d
commit 3814163373
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 136 additions and 22 deletions

View File

@ -436,7 +436,7 @@ $(libcppdir)/checkboost.o: lib/checkboost.cpp lib/check.h lib/checkboost.h lib/c
$(libcppdir)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkbufferoverrun.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkbufferoverrun.o $(libcppdir)/checkbufferoverrun.cpp
$(libcppdir)/checkclass.o: lib/checkclass.cpp lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(libcppdir)/checkclass.o: lib/checkclass.cpp externals/tinyxml2/tinyxml2.h lib/astutils.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkclass.o $(libcppdir)/checkclass.cpp
$(libcppdir)/checkcondition.o: lib/checkcondition.cpp lib/astutils.h lib/check.h lib/checkcondition.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
@ -478,7 +478,7 @@ $(libcppdir)/checkstl.o: lib/checkstl.cpp lib/astutils.h lib/check.h lib/checknu
$(libcppdir)/checkstring.o: lib/checkstring.cpp lib/astutils.h lib/check.h lib/checkstring.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checkstring.o $(libcppdir)/checkstring.cpp
$(libcppdir)/checktype.o: lib/checktype.cpp lib/check.h lib/checktype.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(libcppdir)/checktype.o: lib/checktype.cpp lib/astutils.h lib/check.h lib/checktype.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/checktype.o $(libcppdir)/checktype.cpp
$(libcppdir)/checkuninitvar.o: lib/checkuninitvar.cpp lib/astutils.h lib/check.h lib/checknullpointer.h lib/checkuninitvar.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
@ -547,7 +547,7 @@ $(libcppdir)/reverseanalyzer.o: lib/reverseanalyzer.cpp lib/analyzer.h lib/astut
$(libcppdir)/settings.o: lib/settings.cpp lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/timer.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/settings.o $(libcppdir)/settings.cpp
$(libcppdir)/summaries.o: lib/summaries.cpp lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/utils.h lib/valueflow.h
$(libcppdir)/summaries.o: lib/summaries.cpp lib/analyzerinfo.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/summaries.o $(libcppdir)/summaries.cpp
$(libcppdir)/suppressions.o: lib/suppressions.cpp externals/tinyxml2/tinyxml2.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/mathlib.h lib/path.h lib/suppressions.h lib/utils.h
@ -565,7 +565,7 @@ $(libcppdir)/timer.o: lib/timer.cpp lib/config.h lib/timer.h
$(libcppdir)/token.o: lib/token.cpp lib/astutils.h lib/config.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/token.o $(libcppdir)/token.cpp
$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/analyzerinfo.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(libcppdir)/tokenize.o: lib/tokenize.cpp externals/simplecpp/simplecpp.h lib/check.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/summaries.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h
$(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o $(libcppdir)/tokenize.o $(libcppdir)/tokenize.cpp
$(libcppdir)/tokenlist.o: lib/tokenlist.cpp externals/simplecpp/simplecpp.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/path.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenlist.h lib/utils.h lib/valueflow.h
@ -625,7 +625,7 @@ test/testcharvar.o: test/testcharvar.cpp lib/check.h lib/checkother.h lib/config
test/testclangimport.o: test/testclangimport.cpp lib/clangimport.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testclangimport.o test/testclangimport.cpp
test/testclass.o: test/testclass.cpp externals/tinyxml2/tinyxml2.h lib/check.h lib/checkclass.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
test/testclass.o: test/testclass.cpp externals/tinyxml2/tinyxml2.h lib/check.h lib/checkclass.h lib/config.h lib/ctu.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testclass.o test/testclass.cpp
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/redirect.h test/testsuite.h

View File

@ -26,6 +26,7 @@
#include <cstdlib>
#include <limits>
#include <locale>
#include <stdexcept>
#if defined(_MSC_VER) && _MSC_VER <= 1700 // VS2012 doesn't have std::isinf and std::isnan
#define ISINF(x) (!_finite(x))
@ -294,14 +295,22 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str)
{
// hexadecimal numbers:
if (isIntHex(str)) {
const biguint ret = std::stoull(str, nullptr, 16);
return ret;
try {
const biguint ret = std::stoull(str, nullptr, 16);
return ret;
} catch (const std::out_of_range& e) {
throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str + " (" + e.what() +")");
}
}
// octal numbers:
if (isOct(str)) {
const biguint ret = std::stoull(str, nullptr, 8);
return ret;
try {
const biguint ret = std::stoull(str, nullptr, 8);
return ret;
} catch (const std::out_of_range& e) {
throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str + " (" + e.what() +")");
}
}
// binary numbers:
@ -329,8 +338,12 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str)
return static_cast<biguint>(doubleval);
}
const biguint ret = std::stoull(str, nullptr, 10);
return ret;
try {
const biguint ret = std::stoull(str, nullptr, 10);
return ret;
} catch (const std::out_of_range& e) {
throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str + " (" + e.what() +")");
}
}
unsigned int MathLib::encodeMultiChar(const std::string& str)
@ -474,19 +487,22 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str)
{
// hexadecimal numbers:
if (isIntHex(str)) {
if (str[0] == '-') {
const bigint ret = std::stoll(str, nullptr, 16);
return ret;
} else {
try {
const biguint ret = std::stoull(str, nullptr, 16);
return (bigint)ret;
} catch (const std::out_of_range& e) {
throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str + " (" + e.what() +")");
}
}
// octal numbers:
if (isOct(str)) {
const bigint ret = std::stoll(str, nullptr, 8);
return ret;
try {
const biguint ret = std::stoull(str, nullptr, 8);
return ret;
} catch (const std::out_of_range& e) {
throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str + " (" + e.what() +")");
}
}
// binary numbers:
@ -520,13 +536,12 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str)
return characterLiteralToLongNumber(getCharLiteral(str));
}
if (str[0] == '-') {
const bigint ret = std::stoll(str, nullptr, 10);
try {
const biguint ret = std::stoull(str, nullptr, 10);
return ret;
} catch (const std::out_of_range& e) {
throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str + " (" + e.what() +")");
}
const biguint ret = std::stoull(str, nullptr, 10);
return ret;
}
// in-place conversion of (sub)string to double. Requires no heap.

View File

@ -20,6 +20,8 @@
#include "mathlib.h"
#include "testsuite.h"
#include <limits>
struct InternalError;
@ -370,6 +372,103 @@ private:
*/
ASSERT_EQUALS(0x0A00000000000000LL, MathLib::toLongNumber("0x0A00000000000000LL"));
// min/max numeric limits
ASSERT_EQUALS(std::numeric_limits<long long>::min(), MathLib::toLongNumber(std::to_string(std::numeric_limits<long long>::min())));
ASSERT_EQUALS(std::numeric_limits<long long>::max(), MathLib::toLongNumber(std::to_string(std::numeric_limits<long long>::max())));
ASSERT_EQUALS(std::numeric_limits<unsigned long long>::min(), MathLib::toLongNumber(std::to_string(std::numeric_limits<unsigned long long>::min())));
ASSERT_EQUALS(std::numeric_limits<unsigned long long>::max(), MathLib::toLongNumber(std::to_string(std::numeric_limits<unsigned long long>::max())));
ASSERT_EQUALS(std::numeric_limits<long long>::min(), MathLib::toULongNumber(std::to_string(std::numeric_limits<long long>::min())));
ASSERT_EQUALS(std::numeric_limits<long long>::max(), MathLib::toULongNumber(std::to_string(std::numeric_limits<long long>::max())));
ASSERT_EQUALS(std::numeric_limits<unsigned long long>::min(), MathLib::toULongNumber(std::to_string(std::numeric_limits<unsigned long long>::min())));
ASSERT_EQUALS(std::numeric_limits<unsigned long long>::max(), MathLib::toULongNumber(std::to_string(std::numeric_limits<unsigned long long>::max())));
// min/max and out-of-bounds - hex
{
const MathLib::bigint i = 0xFFFFFFFFFFFFFFFF;
ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i)));
ASSERT_EQUALS(i, MathLib::toLongNumber("0xFFFFFFFFFFFFFFFF"));
}
{
const MathLib::biguint u = 0xFFFFFFFFFFFFFFFF;
ASSERT_EQUALS(u, MathLib::toULongNumber(std::to_string(u)));
ASSERT_EQUALS(u, MathLib::toULongNumber("0xFFFFFFFFFFFFFFFF"));
}
{
const MathLib::bigint i = -0xFFFFFFFFFFFFFFFF;
ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i)));
ASSERT_EQUALS(i, MathLib::toLongNumber("-0xFFFFFFFFFFFFFFFF"));
}
{
const MathLib::biguint u = -0xFFFFFFFFFFFFFFFF;
ASSERT_EQUALS(u, MathLib::toULongNumber(std::to_string(u)));
ASSERT_EQUALS(u, MathLib::toULongNumber("-0xFFFFFFFFFFFFFFFF"));
}
ASSERT_THROW(MathLib::toLongNumber("0x10000000000000000"), InternalError);
ASSERT_THROW(MathLib::toULongNumber("0x10000000000000000"), InternalError);
ASSERT_THROW(MathLib::toLongNumber("-0x10000000000000000"), InternalError);
ASSERT_THROW(MathLib::toULongNumber("-0x10000000000000000"), InternalError);
// min/max and out-of-bounds - octal
{
const MathLib::bigint i = 01777777777777777777777;
ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i)));
ASSERT_EQUALS(i, MathLib::toLongNumber("01777777777777777777777"));
}
{
const MathLib::biguint u = 01777777777777777777777;
ASSERT_EQUALS(u, MathLib::toULongNumber(std::to_string(u)));
ASSERT_EQUALS(u, MathLib::toULongNumber("01777777777777777777777"));
}
{
const MathLib::bigint i = -01777777777777777777777;
ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i)));
ASSERT_EQUALS(i, MathLib::toLongNumber("-01777777777777777777777"));
}
{
const MathLib::biguint u = -01777777777777777777777;
ASSERT_EQUALS(u, MathLib::toULongNumber(std::to_string(u)));
ASSERT_EQUALS(u, MathLib::toULongNumber("-01777777777777777777777"));
}
ASSERT_THROW(MathLib::toLongNumber("02000000000000000000000"), InternalError);
ASSERT_THROW(MathLib::toULongNumber("02000000000000000000000"), InternalError);
ASSERT_THROW(MathLib::toLongNumber("-02000000000000000000000"), InternalError);
ASSERT_THROW(MathLib::toULongNumber("-02000000000000000000000"), InternalError);
// min/max and out-of-bounds - decimal
{
const MathLib::bigint i = 18446744073709551615;
ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i)));
ASSERT_EQUALS(i, MathLib::toLongNumber("18446744073709551615"));
}
{
const MathLib::biguint u = 18446744073709551615;
ASSERT_EQUALS(u, MathLib::toULongNumber(std::to_string(u)));
ASSERT_EQUALS(u, MathLib::toULongNumber("18446744073709551615"));
}
{
const MathLib::bigint i = -18446744073709551615;
ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i)));
ASSERT_EQUALS(i, MathLib::toLongNumber("-18446744073709551615"));
}
{
const MathLib::biguint u = -18446744073709551615;
ASSERT_EQUALS(u, MathLib::toULongNumber(std::to_string(u)));
ASSERT_EQUALS(u, MathLib::toULongNumber("-18446744073709551615"));
}
ASSERT_THROW(MathLib::toLongNumber("18446744073709551616"), InternalError);
ASSERT_THROW(MathLib::toULongNumber("18446744073709551616"), InternalError);
ASSERT_THROW(MathLib::toLongNumber("-18446744073709551616"), InternalError);
ASSERT_THROW(MathLib::toULongNumber("-18446744073709551616"), InternalError);
// TODO: test binary
// TODO: test floating point
// TODO: test with 128-bit values
}
void toDoubleNumber() const {