From 74d554e32a1a5479550b9f336ad0e99ec4651841 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 00:35:46 +0100 Subject: [PATCH 01/17] testmathlib.cpp: split `toULongNumber` into separate test case --- test/testmathlib.cpp | 119 +++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 50 deletions(-) diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index db3992747ed..1665c3f2fa0 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -54,6 +54,7 @@ class TestMathLib : public TestFixture { TEST_CASE(calculate1); TEST_CASE(typesuffix); TEST_CASE(toLongNumber); + TEST_CASE(toULongNumber); TEST_CASE(toDoubleNumber); TEST_CASE(naninf); TEST_CASE(isNullValue); @@ -305,6 +306,74 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(-8552249625308161526, MathLib::toLongNumber("0x89504e470d0a1a0a")); ASSERT_EQUALS(-8481036456200365558, MathLib::toLongNumber("0x8a4d4e470d0a1a0a")); + + // from long long + /* + * ASSERT_EQUALS(0xFF00000000000000LL, MathLib::toLongNumber("0xFF00000000000000LL")); + * This does not work in a portable way! + * While it succeeds on 32bit Visual Studio it fails on Linux 64bit because it is greater than 0x7FFFFFFFFFFFFFFF (=LLONG_MAX) + */ + + ASSERT_EQUALS(0x0A00000000000000LL, MathLib::toLongNumber("0x0A00000000000000LL")); + + // min/max numeric limits + ASSERT_EQUALS(std::numeric_limits::min(), MathLib::toLongNumber(std::to_string(std::numeric_limits::min()))); + ASSERT_EQUALS(std::numeric_limits::max(), MathLib::toLongNumber(std::to_string(std::numeric_limits::max()))); + ASSERT_EQUALS(std::numeric_limits::min(), MathLib::toLongNumber(std::to_string(std::numeric_limits::min()))); + ASSERT_EQUALS(std::numeric_limits::max(), MathLib::toLongNumber(std::to_string(std::numeric_limits::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::bigint i = -0xFFFFFFFFFFFFFFFF; + ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i))); + ASSERT_EQUALS(i, MathLib::toLongNumber("-0xFFFFFFFFFFFFFFFF")); + } + + ASSERT_THROW(MathLib::toLongNumber("0x10000000000000000"), InternalError); + ASSERT_THROW(MathLib::toLongNumber("-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::bigint i = -01777777777777777777777; + ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i))); + ASSERT_EQUALS(i, MathLib::toLongNumber("-01777777777777777777777")); + } + + ASSERT_THROW(MathLib::toLongNumber("02000000000000000000000"), InternalError); + ASSERT_THROW(MathLib::toLongNumber("-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::bigint i = -18446744073709551615; + ASSERT_EQUALS(i, MathLib::toLongNumber(std::to_string(i))); + ASSERT_EQUALS(i, MathLib::toLongNumber("-18446744073709551615")); + } + + ASSERT_THROW(MathLib::toLongNumber("18446744073709551616"), InternalError); + ASSERT_THROW(MathLib::toLongNumber("-18446744073709551616"), InternalError); + + // TODO: test binary + // TODO: test floating point + + // TODO: test with 128-bit values + } + + void toULongNumber() const { ASSERT_EQUALS(9894494448401390090ULL, MathLib::toULongNumber("0x89504e470d0a1a0a")); ASSERT_EQUALS(9965707617509186058ULL, MathLib::toULongNumber("0x8a4d4e470d0a1a0a")); @@ -330,105 +399,55 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(9U, MathLib::toULongNumber("011")); ASSERT_EQUALS(5U, MathLib::toULongNumber("0b101")); - // from long long - /* - * ASSERT_EQUALS(0xFF00000000000000LL, MathLib::toLongNumber("0xFF00000000000000LL")); - * This does not work in a portable way! - * While it succeeds on 32bit Visual Studio it fails on Linux 64bit because it is greater than 0x7FFFFFFFFFFFFFFF (=LLONG_MAX) - */ - - ASSERT_EQUALS(0x0A00000000000000LL, MathLib::toLongNumber("0x0A00000000000000LL")); - // min/max numeric limits - ASSERT_EQUALS(std::numeric_limits::min(), MathLib::toLongNumber(std::to_string(std::numeric_limits::min()))); - ASSERT_EQUALS(std::numeric_limits::max(), MathLib::toLongNumber(std::to_string(std::numeric_limits::max()))); - ASSERT_EQUALS(std::numeric_limits::min(), MathLib::toLongNumber(std::to_string(std::numeric_limits::min()))); - ASSERT_EQUALS(std::numeric_limits::max(), MathLib::toLongNumber(std::to_string(std::numeric_limits::max()))); - ASSERT_EQUALS(std::numeric_limits::min(), MathLib::toULongNumber(std::to_string(std::numeric_limits::min()))); ASSERT_EQUALS(std::numeric_limits::max(), MathLib::toULongNumber(std::to_string(std::numeric_limits::max()))); ASSERT_EQUALS(std::numeric_limits::min(), MathLib::toULongNumber(std::to_string(std::numeric_limits::min()))); ASSERT_EQUALS(std::numeric_limits::max(), MathLib::toULongNumber(std::to_string(std::numeric_limits::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 From d71e86d34bb92cb5660e67eca044adeea4adbbf2 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 00:41:08 +0100 Subject: [PATCH 02/17] testmathlib.cpp: aligned tests in `toLongNumber` and `toULongNumber` --- test/testmathlib.cpp | 94 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 81 insertions(+), 13 deletions(-) diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 1665c3f2fa0..883abd3a115 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -251,6 +251,18 @@ class TestMathLib : public TestFixture { } void toLongNumber() const { + // zero input + ASSERT_EQUALS(0, MathLib::toLongNumber("0")); + ASSERT_EQUALS(0, MathLib::toLongNumber("-0")); + ASSERT_EQUALS(0, MathLib::toLongNumber("+0")); + ASSERT_EQUALS(0U, MathLib::toLongNumber("0U")); + + ASSERT_EQUALS(1U, MathLib::toLongNumber("1U")); + ASSERT_EQUALS(10000U, MathLib::toLongNumber("1e4")); + ASSERT_EQUALS(10000U, MathLib::toLongNumber("1e4")); + ASSERT_EQUALS(0xFF00000000000000UL, MathLib::toLongNumber("0xFF00000000000000UL")); + ASSERT_EQUALS(0x0A00000000000000UL, MathLib::toLongNumber("0x0A00000000000000UL")); + // from hex ASSERT_EQUALS(0, MathLib::toLongNumber("0x0")); ASSERT_EQUALS(0, MathLib::toLongNumber("-0x0")); @@ -280,6 +292,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(1, MathLib::toLongNumber("0b1LLU")); ASSERT_EQUALS(1, MathLib::toLongNumber("+0b1")); ASSERT_EQUALS(-1, MathLib::toLongNumber("-0b1")); + ASSERT_EQUALS(9U, MathLib::toLongNumber("011")); + ASSERT_EQUALS(5U, MathLib::toLongNumber("0b101")); ASSERT_EQUALS(215, MathLib::toLongNumber("0b11010111")); ASSERT_EQUALS(-215, MathLib::toLongNumber("-0b11010111")); ASSERT_EQUALS(215, MathLib::toLongNumber("0B11010111")); @@ -374,30 +388,84 @@ class TestMathLib : public TestFixture { } void toULongNumber() const { - ASSERT_EQUALS(9894494448401390090ULL, MathLib::toULongNumber("0x89504e470d0a1a0a")); - ASSERT_EQUALS(9965707617509186058ULL, MathLib::toULongNumber("0x8a4d4e470d0a1a0a")); - // zero input ASSERT_EQUALS(0, MathLib::toULongNumber("0")); ASSERT_EQUALS(0, MathLib::toULongNumber("-0")); ASSERT_EQUALS(0, MathLib::toULongNumber("+0")); ASSERT_EQUALS(0U, MathLib::toULongNumber("0U")); - ASSERT_EQUALS(0, MathLib::toULongNumber("-0x0")); ASSERT_EQUALS(1U, MathLib::toULongNumber("1U")); ASSERT_EQUALS(10000U, MathLib::toULongNumber("1e4")); ASSERT_EQUALS(10000U, MathLib::toULongNumber("1e4")); ASSERT_EQUALS(0xFF00000000000000UL, MathLib::toULongNumber("0xFF00000000000000UL")); ASSERT_EQUALS(0x0A00000000000000UL, MathLib::toULongNumber("0x0A00000000000000UL")); - ASSERT_EQUALS(0, MathLib::toULongNumber("0b0")); - ASSERT_EQUALS(1, MathLib::toULongNumber("0b1")); - ASSERT_EQUALS(1, MathLib::toULongNumber("0b1U")); - ASSERT_EQUALS(1, MathLib::toULongNumber("0b1L")); - ASSERT_EQUALS(1, MathLib::toULongNumber("0b1LU")); - ASSERT_EQUALS(1, MathLib::toULongNumber("0b1LL")); - ASSERT_EQUALS(1, MathLib::toULongNumber("0b1LLU")); - ASSERT_EQUALS(9U, MathLib::toULongNumber("011")); - ASSERT_EQUALS(5U, MathLib::toULongNumber("0b101")); + + // from hex + ASSERT_EQUALS(0, MathLib::toULongNumber("0x0")); + ASSERT_EQUALS(0, MathLib::toULongNumber("-0x0")); + ASSERT_EQUALS(0, MathLib::toULongNumber("+0x0")); + ASSERT_EQUALS(10, MathLib::toULongNumber("0xa")); + ASSERT_EQUALS(10995, MathLib::toULongNumber("0x2AF3")); + ASSERT_EQUALS(-10, MathLib::toULongNumber("-0xa")); + ASSERT_EQUALS(-10995, MathLib::toULongNumber("-0x2AF3")); + ASSERT_EQUALS(10, MathLib::toULongNumber("+0xa")); + ASSERT_EQUALS(10995, MathLib::toULongNumber("+0x2AF3")); + + // from octal + ASSERT_EQUALS(8, MathLib::toULongNumber("010")); + ASSERT_EQUALS(8, MathLib::toULongNumber("+010")); + ASSERT_EQUALS(-8, MathLib::toULongNumber("-010")); + ASSERT_EQUALS(125, MathLib::toULongNumber("0175")); + ASSERT_EQUALS(125, MathLib::toULongNumber("+0175")); + ASSERT_EQUALS(-125, MathLib::toULongNumber("-0175")); + + // from binary + ASSERT_EQUALS(0, MathLib::toULongNumber("0b0")); + ASSERT_EQUALS(1, MathLib::toULongNumber("0b1")); + ASSERT_EQUALS(1, MathLib::toULongNumber("0b1U")); + ASSERT_EQUALS(1, MathLib::toULongNumber("0b1L")); + ASSERT_EQUALS(1, MathLib::toULongNumber("0b1LU")); + ASSERT_EQUALS(1, MathLib::toULongNumber("0b1LL")); + ASSERT_EQUALS(1, MathLib::toULongNumber("0b1LLU")); + ASSERT_EQUALS(1, MathLib::toULongNumber("+0b1")); + ASSERT_EQUALS(-1, MathLib::toULongNumber("-0b1")); + ASSERT_EQUALS(9U, MathLib::toULongNumber("011")); + ASSERT_EQUALS(5U, MathLib::toULongNumber("0b101")); + ASSERT_EQUALS(215, MathLib::toULongNumber("0b11010111")); + ASSERT_EQUALS(-215, MathLib::toULongNumber("-0b11010111")); + ASSERT_EQUALS(215, MathLib::toULongNumber("0B11010111")); + + // from base 10 + ASSERT_EQUALS(10, MathLib::toULongNumber("10")); + ASSERT_EQUALS(10, MathLib::toULongNumber("10.")); + ASSERT_EQUALS(10, MathLib::toULongNumber("10.0")); + ASSERT_EQUALS(100, MathLib::toULongNumber("10E+1")); + ASSERT_EQUALS(1, MathLib::toULongNumber("10E-1")); + ASSERT_EQUALS(100, MathLib::toULongNumber("+10E+1")); + ASSERT_EQUALS(-1, MathLib::toULongNumber("-10E-1")); + ASSERT_EQUALS(100, MathLib::toULongNumber("+10.E+1")); + ASSERT_EQUALS(-1, MathLib::toULongNumber("-10.E-1")); + ASSERT_EQUALS(100, MathLib::toULongNumber("+10.0E+1")); + ASSERT_EQUALS(-1, MathLib::toULongNumber("-10.0E-1")); + + // from char + ASSERT_EQUALS((int)('A'), MathLib::toULongNumber("'A'")); + ASSERT_EQUALS((int)('\x10'), MathLib::toULongNumber("'\\x10'")); + ASSERT_EQUALS((int)('\100'), MathLib::toULongNumber("'\\100'")); + ASSERT_EQUALS((int)('\200'), MathLib::toULongNumber("'\\200'")); + ASSERT_EQUALS((int)(L'A'), MathLib::toULongNumber("L'A'")); + + ASSERT_EQUALS(9894494448401390090ULL, MathLib::toULongNumber("0x89504e470d0a1a0a")); + ASSERT_EQUALS(9965707617509186058ULL, MathLib::toULongNumber("0x8a4d4e470d0a1a0a")); + + // from long long + /* + * ASSERT_EQUALS(0xFF00000000000000LL, MathLib::toULongNumber("0xFF00000000000000LL")); + * This does not work in a portable way! + * While it succeeds on 32bit Visual Studio it fails on Linux 64bit because it is greater than 0x7FFFFFFFFFFFFFFF (=LLONG_MAX) + */ + + ASSERT_EQUALS(0x0A00000000000000LL, MathLib::toULongNumber("0x0A00000000000000LL")); // min/max numeric limits ASSERT_EQUALS(std::numeric_limits::min(), MathLib::toULongNumber(std::to_string(std::numeric_limits::min()))); From 32bcbc82b41c6c1c1025020b796f5741f39c3c13 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 00:43:03 +0100 Subject: [PATCH 03/17] mathlib.cpp: fixed handling of negative binary numbers in `toULongNumber()` --- lib/mathlib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 5f0892ae331..eec2ba1069b 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -318,8 +318,8 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) if (str[i] == '1') ret |= 1; } - /* if (str[0] == '-') - ret = -ret; */ + if (str[0] == '-') + ret = -ret; return ret; } From 1eff4f1571257b6b11c75c754b3246e1370e6bd7 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 00:45:40 +0100 Subject: [PATCH 04/17] mathlib.cpp: added handling of `std::invalid_argument` to `std::stoull()` calls --- lib/mathlib.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index eec2ba1069b..733cec40e57 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -295,6 +295,8 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) return ret; } catch (const std::out_of_range& e) { throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str + " (" + e.what() +")"); + } catch (const std::invalid_argument& e) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str + " (" + e.what() +")"); } } @@ -305,6 +307,8 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) return ret; } catch (const std::out_of_range& e) { throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str + " (" + e.what() +")"); + } catch (const std::invalid_argument& e) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str + " (" + e.what() +")"); } } @@ -338,6 +342,8 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) return ret; } catch (const std::out_of_range& e) { throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str + " (" + e.what() +")"); + } catch (const std::invalid_argument& e) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str + " (" + e.what() +")"); } } @@ -357,6 +363,8 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) return (bigint)ret; } catch (const std::out_of_range& e) { throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str + " (" + e.what() +")"); + } catch (const std::invalid_argument& e) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str + " (" + e.what() +")"); } } @@ -367,6 +375,8 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) return ret; } catch (const std::out_of_range& e) { throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str + " (" + e.what() +")"); + } catch (const std::invalid_argument& e) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str + " (" + e.what() +")"); } } @@ -405,6 +415,8 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) return ret; } catch (const std::out_of_range& e) { throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str + " (" + e.what() +")"); + } catch (const std::invalid_argument& e) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str + " (" + e.what() +")"); } } From 5b3ff5ef17e1e007fe665653d7f26c15c0ff866d Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 00:50:36 +0100 Subject: [PATCH 05/17] mathlib.cpp: added missing handling of char literals to `toULongNumber()` --- lib/mathlib.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 733cec40e57..ade7726b6f8 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -337,6 +337,9 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) return static_cast(doubleval); } + if (isCharLiteral(str)) + return simplecpp::characterLiteralToLL(str); + try { const biguint ret = std::stoull(str, nullptr, 10); return ret; From 1114b90f289ec8143bde02aacd57673eb12a5bcd Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 00:55:30 +0100 Subject: [PATCH 06/17] testmathlib.cpp: check exception messages --- test/testmathlib.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 883abd3a115..06436637452 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -146,13 +146,13 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS("5.0", MathLib::divide("25.5", "5.1")); ASSERT_EQUALS("7.0", MathLib::divide("21.", "3")); ASSERT_EQUALS("1", MathLib::divide("3", "2")); - ASSERT_THROW(MathLib::divide("123", "0"), InternalError); // decimal zero: throw - ASSERT_THROW(MathLib::divide("123", "00"), InternalError); // octal zero: throw - ASSERT_THROW(MathLib::divide("123", "0x0"), InternalError); // hex zero: throw + ASSERT_THROW_EQUALS(MathLib::divide("123", "0"), InternalError, "Internal Error: Division by zero"); // decimal zero: throw + ASSERT_THROW_EQUALS(MathLib::divide("123", "00"), InternalError, "Internal Error: Division by zero"); // octal zero: throw + ASSERT_THROW_EQUALS(MathLib::divide("123", "0x0"), InternalError, "Internal Error: Division by zero"); // hex zero: throw MathLib::divide("123", "0.0f"); // float zero: don't throw MathLib::divide("123", "0.0"); // double zero: don't throw MathLib::divide("123", "0.0L"); // long double zero: don't throw - ASSERT_THROW(MathLib::divide("-9223372036854775808", "-1"), InternalError); // #4520 - out of range => throw + ASSERT_THROW_EQUALS(MathLib::divide("-9223372036854775808", "-1"), InternalError, "Internal Error: Division overflow"); // #4520 - out of range => throw ASSERT_EQUALS("4611686018427387904", MathLib::divide("-9223372036854775808", "-2")); // #6679 @@ -167,7 +167,7 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS("1", MathLib::calculate("0", "1", '^')); // Unknown action should throw exception - ASSERT_THROW(MathLib::calculate("1","2",'j'),InternalError); + ASSERT_THROW_EQUALS(MathLib::calculate("1","2",'j'),InternalError, "Unexpected action 'j' in MathLib::calculate(). Please report this to Cppcheck developers."); } void calculate1() const { @@ -184,7 +184,7 @@ class TestMathLib : public TestFixture { MathLib::calculate("123", "0.0", '%'); // don't throw #endif - ASSERT_THROW(MathLib::calculate("123", "0", '%'), InternalError); // throw + ASSERT_THROW_EQUALS(MathLib::calculate("123", "0", '%'), InternalError, "Internal Error: Division by zero"); // throw ASSERT_EQUALS("0", MathLib::calculate("1", "1", '^')); ASSERT_EQUALS("3", MathLib::calculate("2", "1", '^')); @@ -348,8 +348,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(i, MathLib::toLongNumber("-0xFFFFFFFFFFFFFFFF")); } - ASSERT_THROW(MathLib::toLongNumber("0x10000000000000000"), InternalError); - ASSERT_THROW(MathLib::toLongNumber("-0x10000000000000000"), InternalError); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("0x10000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 0x10000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("-0x10000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -0x10000000000000000 (stoull)"); // min/max and out-of-bounds - octal { @@ -363,8 +363,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(i, MathLib::toLongNumber("-01777777777777777777777")); } - ASSERT_THROW(MathLib::toLongNumber("02000000000000000000000"), InternalError); - ASSERT_THROW(MathLib::toLongNumber("-02000000000000000000000"), InternalError); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("02000000000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 02000000000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("-02000000000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -02000000000000000000000 (stoull)"); // min/max and out-of-bounds - decimal { @@ -378,8 +378,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(i, MathLib::toLongNumber("-18446744073709551615")); } - ASSERT_THROW(MathLib::toLongNumber("18446744073709551616"), InternalError); - ASSERT_THROW(MathLib::toLongNumber("-18446744073709551616"), InternalError); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 18446744073709551616 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -18446744073709551616 (stoull)"); // TODO: test binary // TODO: test floating point @@ -485,8 +485,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(u, MathLib::toULongNumber("-0xFFFFFFFFFFFFFFFF")); } - ASSERT_THROW(MathLib::toULongNumber("0x10000000000000000"), InternalError); - ASSERT_THROW(MathLib::toULongNumber("-0x10000000000000000"), InternalError); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("0x10000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 0x10000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("-0x10000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -0x10000000000000000 (stoull)"); // min/max and out-of-bounds - octal { @@ -500,8 +500,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(u, MathLib::toULongNumber("-01777777777777777777777")); } - ASSERT_THROW(MathLib::toULongNumber("02000000000000000000000"), InternalError); - ASSERT_THROW(MathLib::toULongNumber("-02000000000000000000000"), InternalError); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("02000000000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 02000000000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("-02000000000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -02000000000000000000000 (stoull)"); // min/max and out-of-bounds - decimal { @@ -515,8 +515,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(u, MathLib::toULongNumber("-18446744073709551615")); } - ASSERT_THROW(MathLib::toULongNumber("18446744073709551616"), InternalError); - ASSERT_THROW(MathLib::toULongNumber("-18446744073709551616"), InternalError); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 18446744073709551616 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -18446744073709551616 (stoull)"); // TODO: test binary // TODO: test floating point From 2dd2dfa832c1956c1c486e5e39e2f0d5cbf9c2cb Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 00:58:50 +0100 Subject: [PATCH 07/17] testmathlib.cpp: added tests which produce `std::invalid_argument` exception --- test/testmathlib.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 06436637452..e50ec3f99ed 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -381,6 +381,8 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toLongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 18446744073709551616 (stoull)"); ASSERT_THROW_EQUALS(MathLib::toLongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -18446744073709551616 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("invalid"), InternalError, "Internal Error. MathLib::toLongNumber: invalid_argument: invalid (stoull)"); + // TODO: test binary // TODO: test floating point @@ -518,6 +520,8 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toULongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 18446744073709551616 (stoull)"); ASSERT_THROW_EQUALS(MathLib::toULongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -18446744073709551616 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("invalid"), InternalError, "Internal Error. MathLib::toULongNumber: invalid_argument: invalid (stoull)"); + // TODO: test binary // TODO: test floating point From e7edc7bc42003bb55728add09c2885cc7aab35db Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 01:01:58 +0100 Subject: [PATCH 08/17] MathLib: removed pointless info from `to{U}LongNumber()` exception messages --- lib/mathlib.cpp | 48 ++++++++++++++++++++++---------------------- test/testmathlib.cpp | 28 +++++++++++++------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index ade7726b6f8..e90c09a897c 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -293,10 +293,10 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) 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() +")"); - } catch (const std::invalid_argument& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str + " (" + e.what() +")"); + } catch (const std::out_of_range& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str); + } catch (const std::invalid_argument& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str); } } @@ -305,10 +305,10 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) 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() +")"); - } catch (const std::invalid_argument& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str + " (" + e.what() +")"); + } catch (const std::out_of_range& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str); + } catch (const std::invalid_argument& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str); } } @@ -343,10 +343,10 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) 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() +")"); - } catch (const std::invalid_argument& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str + " (" + e.what() +")"); + } catch (const std::out_of_range& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str); + } catch (const std::invalid_argument& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: invalid_argument: " + str); } } @@ -364,10 +364,10 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) 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() +")"); - } catch (const std::invalid_argument& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str + " (" + e.what() +")"); + } catch (const std::out_of_range& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str); + } catch (const std::invalid_argument& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str); } } @@ -376,10 +376,10 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) 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() +")"); - } catch (const std::invalid_argument& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str + " (" + e.what() +")"); + } catch (const std::out_of_range& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str); + } catch (const std::invalid_argument& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str); } } @@ -416,10 +416,10 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) 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() +")"); - } catch (const std::invalid_argument& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str + " (" + e.what() +")"); + } catch (const std::out_of_range& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str); + } catch (const std::invalid_argument& /*e*/) { + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: invalid_argument: " + str); } } diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index e50ec3f99ed..d2b7666af76 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -348,8 +348,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(i, MathLib::toLongNumber("-0xFFFFFFFFFFFFFFFF")); } - ASSERT_THROW_EQUALS(MathLib::toLongNumber("0x10000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 0x10000000000000000 (stoull)"); - ASSERT_THROW_EQUALS(MathLib::toLongNumber("-0x10000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -0x10000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("0x10000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 0x10000000000000000"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("-0x10000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -0x10000000000000000"); // min/max and out-of-bounds - octal { @@ -363,8 +363,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(i, MathLib::toLongNumber("-01777777777777777777777")); } - ASSERT_THROW_EQUALS(MathLib::toLongNumber("02000000000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 02000000000000000000000 (stoull)"); - ASSERT_THROW_EQUALS(MathLib::toLongNumber("-02000000000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -02000000000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("02000000000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 02000000000000000000000"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("-02000000000000000000000"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -02000000000000000000000"); // min/max and out-of-bounds - decimal { @@ -378,10 +378,10 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(i, MathLib::toLongNumber("-18446744073709551615")); } - ASSERT_THROW_EQUALS(MathLib::toLongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 18446744073709551616 (stoull)"); - ASSERT_THROW_EQUALS(MathLib::toLongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -18446744073709551616 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: 18446744073709551616"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toLongNumber: out_of_range: -18446744073709551616"); - ASSERT_THROW_EQUALS(MathLib::toLongNumber("invalid"), InternalError, "Internal Error. MathLib::toLongNumber: invalid_argument: invalid (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("invalid"), InternalError, "Internal Error. MathLib::toLongNumber: invalid_argument: invalid"); // TODO: test binary // TODO: test floating point @@ -487,8 +487,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(u, MathLib::toULongNumber("-0xFFFFFFFFFFFFFFFF")); } - ASSERT_THROW_EQUALS(MathLib::toULongNumber("0x10000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 0x10000000000000000 (stoull)"); - ASSERT_THROW_EQUALS(MathLib::toULongNumber("-0x10000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -0x10000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("0x10000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 0x10000000000000000"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("-0x10000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -0x10000000000000000"); // min/max and out-of-bounds - octal { @@ -502,8 +502,8 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(u, MathLib::toULongNumber("-01777777777777777777777")); } - ASSERT_THROW_EQUALS(MathLib::toULongNumber("02000000000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 02000000000000000000000 (stoull)"); - ASSERT_THROW_EQUALS(MathLib::toULongNumber("-02000000000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -02000000000000000000000 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("02000000000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 02000000000000000000000"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("-02000000000000000000000"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -02000000000000000000000"); // min/max and out-of-bounds - decimal { @@ -517,10 +517,10 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS(u, MathLib::toULongNumber("-18446744073709551615")); } - ASSERT_THROW_EQUALS(MathLib::toULongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 18446744073709551616 (stoull)"); - ASSERT_THROW_EQUALS(MathLib::toULongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -18446744073709551616 (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: 18446744073709551616"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("-18446744073709551616"), InternalError, "Internal Error. MathLib::toULongNumber: out_of_range: -18446744073709551616"); - ASSERT_THROW_EQUALS(MathLib::toULongNumber("invalid"), InternalError, "Internal Error. MathLib::toULongNumber: invalid_argument: invalid (stoull)"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("invalid"), InternalError, "Internal Error. MathLib::toULongNumber: invalid_argument: invalid"); // TODO: test binary // TODO: test floating point From 5553908e863ec64edd99918f03f4c5e3839b28e8 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 01:14:03 +0100 Subject: [PATCH 09/17] fixed #10695 - make sure the whole input is being consumed in `MathLib::to{U}LongNumber()` --- lib/mathlib.cpp | 16 ++++++++++++-- test/testmathlib.cpp | 50 +++++++++++++++++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index e90c09a897c..c342b17239e 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -341,7 +341,13 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) return simplecpp::characterLiteralToLL(str); try { - const biguint ret = std::stoull(str, nullptr, 10); + std::size_t idx = 0; + const biguint ret = std::stoull(str, &idx, 10); + if (idx != str.size()) { + const std::string s = str.substr(idx); + if (s.find_first_not_of("LlUu") != std::string::npos && s != "i64" && s != "ui64") + throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: input was not completely consumed: " + str); + } return ret; } catch (const std::out_of_range& /*e*/) { throw InternalError(nullptr, "Internal Error. MathLib::toULongNumber: out_of_range: " + str); @@ -414,7 +420,13 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) return simplecpp::characterLiteralToLL(str); try { - const biguint ret = std::stoull(str, nullptr, 10); + std::size_t idx = 0; + const biguint ret = std::stoull(str, &idx, 10); + if (idx != str.size()) { + const std::string s = str.substr(idx); + if (s.find_first_not_of("LlUu") != std::string::npos && s != "i64" && s != "ui64") + throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: input was not completely consumed: " + str); + } return ret; } catch (const std::out_of_range& /*e*/) { throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: out_of_range: " + str); diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index d2b7666af76..90bf8387acd 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -252,10 +252,25 @@ class TestMathLib : public TestFixture { void toLongNumber() const { // zero input - ASSERT_EQUALS(0, MathLib::toLongNumber("0")); - ASSERT_EQUALS(0, MathLib::toLongNumber("-0")); - ASSERT_EQUALS(0, MathLib::toLongNumber("+0")); - ASSERT_EQUALS(0U, MathLib::toLongNumber("0U")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0")); + ASSERT_EQUALS(0, MathLib::toLongNumber("-0")); + ASSERT_EQUALS(0, MathLib::toLongNumber("+0")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0L")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0l")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0LL")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0ll")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0U")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0u")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0UL")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0ul")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0ULL")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0ull")); + ASSERT_EQUALS(0, MathLib::toLongNumber("0i64")); // Visual Studio-specific + ASSERT_EQUALS(0, MathLib::toLongNumber("0ui64")); // Visual Studio-specific + + // TODO: needs to fail + //ASSERT_EQUALS(0, MathLib::toLongNumber("0lll")); + //ASSERT_EQUALS(0, MathLib::toLongNumber("0uu")); ASSERT_EQUALS(1U, MathLib::toLongNumber("1U")); ASSERT_EQUALS(10000U, MathLib::toLongNumber("1e4")); @@ -383,6 +398,8 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toLongNumber("invalid"), InternalError, "Internal Error. MathLib::toLongNumber: invalid_argument: invalid"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("1invalid"), InternalError, "Internal Error. MathLib::toLongNumber: input was not completely consumed: 1invalid"); + // TODO: test binary // TODO: test floating point @@ -391,10 +408,25 @@ class TestMathLib : public TestFixture { void toULongNumber() const { // zero input - ASSERT_EQUALS(0, MathLib::toULongNumber("0")); - ASSERT_EQUALS(0, MathLib::toULongNumber("-0")); - ASSERT_EQUALS(0, MathLib::toULongNumber("+0")); - ASSERT_EQUALS(0U, MathLib::toULongNumber("0U")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0")); + ASSERT_EQUALS(0, MathLib::toULongNumber("-0")); + ASSERT_EQUALS(0, MathLib::toULongNumber("+0")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0L")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0l")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0LL")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0ll")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0U")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0u")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0UL")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0ul")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0ULL")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0ull")); + ASSERT_EQUALS(0, MathLib::toULongNumber("0i64")); // Visual Studio-specific + ASSERT_EQUALS(0, MathLib::toULongNumber("0ui64")); // Visual Studio-specific + + // TODO: needs to fail + //ASSERT_EQUALS(0, MathLib::toULongNumber("0lll")); + //ASSERT_EQUALS(0, MathLib::toULongNumber("0uu")); ASSERT_EQUALS(1U, MathLib::toULongNumber("1U")); ASSERT_EQUALS(10000U, MathLib::toULongNumber("1e4")); @@ -522,6 +554,8 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toULongNumber("invalid"), InternalError, "Internal Error. MathLib::toULongNumber: invalid_argument: invalid"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("1invalid"), InternalError, "Internal Error. MathLib::toULongNumber: input was not completely consumed: 1invalid"); + // TODO: test binary // TODO: test floating point From f40781b093bc191ff065defa0754a65c3f9f2ab7 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 09:35:03 +0100 Subject: [PATCH 10/17] mathlib.cpp: use `toDoubleNumber()` in `toULongNumber()` as well --- lib/mathlib.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index c342b17239e..9031fb408b5 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -328,9 +328,10 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) } if (isFloat(str)) { - // Things are going to be less precise now: the value can't b represented in the biguint type. + // Things are going to be less precise now: the value can't be represented in the biguint type. // Use min/max values as an approximation. See #5843 - const double doubleval = std::atof(str.c_str()); + // TODO: bail out when we are out of range? + const double doubleval = toDoubleNumber(str); if (doubleval > (double)std::numeric_limits::max()) return std::numeric_limits::max(); else @@ -407,6 +408,7 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) if (isFloat(str)) { // Things are going to be less precise now: the value can't be represented in the bigint type. // Use min/max values as an approximation. See #5843 + // TODO: bail out when we are out of range? const double doubleval = toDoubleNumber(str); if (doubleval > (double)std::numeric_limits::max()) return std::numeric_limits::max(); From 708162a9aca29b3a1dd1555208c01c8f3575dd6b Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 10:01:40 +0100 Subject: [PATCH 11/17] MathLib: improved handling of invalid input in `toDoubleNumber()` / increased test coverage --- lib/mathlib.cpp | 10 ++++++++-- test/testmathlib.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 9031fb408b5..500a430b71e 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -492,7 +492,7 @@ double MathLib::toDoubleNumber(const std::string &str) try { return simplecpp::characterLiteralToLL(str); } catch (const std::exception& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: characterLiteralToLL(" + str + ") => " + e.what()); + throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: characterLiteralToLL(" + str + ") => " + e.what()); } } if (isIntHex(str)) @@ -508,7 +508,13 @@ double MathLib::toDoubleNumber(const std::string &str) std::istringstream istr(str); istr.imbue(std::locale::classic()); double ret; - istr >> ret; + if (!(istr >> ret)) + throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: conversion failed: " + str); + std::string s; + if (istr >> s) { + if (s.find_first_not_of("FfLl") != std::string::npos) + throw InternalError(nullptr, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: " + str); + } return ret; } diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 90bf8387acd..41d4dfd0bcc 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -399,6 +399,7 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toLongNumber("invalid"), InternalError, "Internal Error. MathLib::toLongNumber: invalid_argument: invalid"); ASSERT_THROW_EQUALS(MathLib::toLongNumber("1invalid"), InternalError, "Internal Error. MathLib::toLongNumber: input was not completely consumed: 1invalid"); + ASSERT_THROW_EQUALS(MathLib::toLongNumber("1 invalid"), InternalError, "Internal Error. MathLib::toLongNumber: input was not completely consumed: 1 invalid"); // TODO: test binary // TODO: test floating point @@ -555,6 +556,7 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toULongNumber("invalid"), InternalError, "Internal Error. MathLib::toULongNumber: invalid_argument: invalid"); ASSERT_THROW_EQUALS(MathLib::toULongNumber("1invalid"), InternalError, "Internal Error. MathLib::toULongNumber: input was not completely consumed: 1invalid"); + ASSERT_THROW_EQUALS(MathLib::toULongNumber("1 invalid"), InternalError, "Internal Error. MathLib::toULongNumber: input was not completely consumed: 1 invalid"); // TODO: test binary // TODO: test floating point @@ -564,9 +566,15 @@ class TestMathLib : public TestFixture { void toDoubleNumber() const { ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1f"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1F"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1l"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1L"), 0.001); ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("0x1"), 0.001); ASSERT_EQUALS_DOUBLE(10.0, MathLib::toDoubleNumber("10"), 0.001); ASSERT_EQUALS_DOUBLE(1000.0, MathLib::toDoubleNumber("10E+2"), 0.001); + ASSERT_EQUALS_DOUBLE(1000.0, MathLib::toDoubleNumber("10E+2l"), 0.001); + ASSERT_EQUALS_DOUBLE(1000.0, MathLib::toDoubleNumber("10E+2L"), 0.001); ASSERT_EQUALS_DOUBLE(100.0, MathLib::toDoubleNumber("1.0E+2"), 0.001); ASSERT_EQUALS_DOUBLE(-100.0, MathLib::toDoubleNumber("-1.0E+2"), 0.001); ASSERT_EQUALS_DOUBLE(-1e+10, MathLib::toDoubleNumber("-1.0E+10"), 1); @@ -574,6 +582,13 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS_DOUBLE(1e+10, MathLib::toDoubleNumber("+1.0E+10"), 1); ASSERT_EQUALS_DOUBLE(100.0, MathLib::toDoubleNumber("1.0E+2"), 0.001); ASSERT_EQUALS_DOUBLE(1e+10, MathLib::toDoubleNumber("1.0E+10"), 1); + + // TODO: needs to fail + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ff"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1FF"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ll"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1LL"), 0.001); + ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E+0"), 0.000001); ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E-0"), 0.000001); ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E+00"), 0.000001); @@ -601,6 +616,19 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS_DOUBLE(9.0, MathLib::toDoubleNumber("0x1.2P3"), 0.000001); ASSERT_EQUALS_DOUBLE(0.0625, MathLib::toDoubleNumber("0x.1P0"), 0.000001); + // from char + ASSERT_EQUALS_DOUBLE((double)('A'), MathLib::toDoubleNumber("'A'"), 0.000001); + ASSERT_EQUALS_DOUBLE((double)('\x10'), MathLib::toDoubleNumber("'\\x10'"), 0.000001); + ASSERT_EQUALS_DOUBLE((double)('\100'), MathLib::toDoubleNumber("'\\100'"), 0.000001); + ASSERT_EQUALS_DOUBLE((double)('\200'), MathLib::toDoubleNumber("'\\200'"), 0.000001); + ASSERT_EQUALS_DOUBLE((double)(L'A'), MathLib::toDoubleNumber("L'A'"), 0.000001); + + ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: invalid"); + + ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1invalid"); + ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.1invalid"); + ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1 invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1 invalid"); + // verify: string --> double --> string conversion ASSERT_EQUALS("1.0", MathLib::toString(MathLib::toDoubleNumber("1.0f"))); ASSERT_EQUALS("1.0", MathLib::toString(MathLib::toDoubleNumber("1.0"))); From 42bc53b8423562e8e27abb49f8496d7f28872de6 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 10:08:15 +0100 Subject: [PATCH 12/17] ubsan.yml: added `report_error_type=1` to `UBSAN_OPTIONS` --- .github/workflows/ubsan.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ubsan.yml b/.github/workflows/ubsan.yml index 344ba51b5ae..a67a4659b77 100644 --- a/.github/workflows/ubsan.yml +++ b/.github/workflows/ubsan.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-22.04 env: - UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1 + UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1:report_error_type=1 steps: - uses: actions/checkout@v3 From 80522d9d41fd8d6ac9882c44013aa5c60a3ee37b Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 10:10:19 +0100 Subject: [PATCH 13/17] mathlib.cpp: fixed UBSAN warning about negative double being out-of-range in `toULongNumber()` --- lib/mathlib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 500a430b71e..78259aee863 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -334,8 +334,8 @@ MathLib::biguint MathLib::toULongNumber(const std::string & str) const double doubleval = toDoubleNumber(str); if (doubleval > (double)std::numeric_limits::max()) return std::numeric_limits::max(); - else - return static_cast(doubleval); + else // cast to bigint to avoid UBSAN warning about negative double being out-of-range + return static_cast(static_cast(doubleval)); } if (isCharLiteral(str)) From 1c36cde29147e7df04fcecadf1d7fd9173ecb240 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 12:18:52 +0100 Subject: [PATCH 14/17] MathLib: fixed incorrect `toString()` result if it contains an exponent --- lib/mathlib.cpp | 2 +- test/testmathlib.cpp | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 78259aee863..6e794d5b96e 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -525,7 +525,7 @@ template<> std::string MathLib::toString(double value) result << value; if (result.str() == "-0") return "0.0"; - if (result.str().find('.') == std::string::npos) + if (result.str().find_first_of(".e") == std::string::npos) return result.str() + ".0"; return result.str(); } diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index 41d4dfd0bcc..b2c8711b21b 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -628,6 +628,7 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1invalid"); ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.1invalid"); ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1 invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1 invalid"); + ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("-1e-08.0"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: -1e-08.0"); // verify: string --> double --> string conversion ASSERT_EQUALS("1.0", MathLib::toString(MathLib::toDoubleNumber("1.0f"))); @@ -1383,6 +1384,9 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS("0.000000", MathLib::toString(0.0L)); ASSERT_EQUALS("0.000000", MathLib::toString(+0.0L)); ASSERT_EQUALS("-0.000000", MathLib::toString(-0.0L)); + + ASSERT_EQUALS("1e-08", MathLib::toString(0.00000001)); + ASSERT_EQUALS("-1e-08", MathLib::toString(-0.00000001)); } void CPP14DigitSeparators() const { // Ticket #7137, #7565 From 91b12335f580c878f0bccfc14382fe71bc813cd3 Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 12:19:38 +0100 Subject: [PATCH 15/17] mathlib.cpp: avoid unnecessary copies in `toString()` --- lib/mathlib.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 6e794d5b96e..330305ba73c 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -523,11 +523,12 @@ template<> std::string MathLib::toString(double value) std::ostringstream result; result.precision(12); result << value; - if (result.str() == "-0") + std::string s = result.str(); + if (s == "-0") return "0.0"; - if (result.str().find_first_of(".e") == std::string::npos) - return result.str() + ".0"; - return result.str(); + if (s.find_first_of(".e") == std::string::npos) + return s + ".0"; + return s; } bool MathLib::isFloat(const std::string &str) From 0927ad40301389a6e6f249c05b801138d8e24fce Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 13:53:12 +0100 Subject: [PATCH 16/17] added CMake option `USE_LIBCXX` to use `libc++` instead of `libstdc++` and also set `LIBCXX_ENABLE_DEBUG_MODE` in `Debug` build --- cmake/compilerDefinitions.cmake | 12 ++++++++---- cmake/compileroptions.cmake | 5 +++++ cmake/options.cmake | 3 ++- cmake/printInfo.cmake | 1 + 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/cmake/compilerDefinitions.cmake b/cmake/compilerDefinitions.cmake index 4a0d94ff294..1dddd81a2f6 100644 --- a/cmake/compilerDefinitions.cmake +++ b/cmake/compilerDefinitions.cmake @@ -13,11 +13,15 @@ if (MSVC) endif() # TODO: this should probably apply to the compiler and not the platform -if (CPPCHK_GLIBCXX_DEBUG AND UNIX) - # TODO: check if this can be enabled again for Clang - also done in Makefile - if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) +if (CPPCHK_GLIBCXX_DEBUG AND UNIX AND CMAKE_BUILD_TYPE STREQUAL "Debug") + if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if (USE_LIBCXX) + add_definitions(-DLIBCXX_ENABLE_DEBUG_MODE) + endif() + else() + # TODO: check if this can be enabled again for Clang - also done in Makefile add_definitions(-D_GLIBCXX_DEBUG) - endif() + endif() endif() if (HAVE_RULES) diff --git a/cmake/compileroptions.cmake b/cmake/compileroptions.cmake index f355fe45bd3..4b9a703c958 100644 --- a/cmake/compileroptions.cmake +++ b/cmake/compileroptions.cmake @@ -65,6 +65,11 @@ elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-gdwarf-4) endif() + if (USE_LIBCXX) + add_compile_options(-stdlib=libc++) + add_link_options(-lc++) + endif() + add_compile_options_safe(-Wno-documentation-unknown-command) # TODO: fix and enable these warnings - or move to suppression list below diff --git a/cmake/options.cmake b/cmake/options.cmake index 1f8f7342ca2..09954a9b123 100644 --- a/cmake/options.cmake +++ b/cmake/options.cmake @@ -42,9 +42,10 @@ option(USE_QT6 "Prefer Qt6 when available" option(HAVE_RULES "Usage of rules (needs PCRE library and headers)" OFF) option(USE_BUNDLED_TINYXML2 "Usage of bundled tinyxml2 library" ON) -option(CPPCHK_GLIBCXX_DEBUG "Usage of _GLIBCXX_DEBUG in Debug build" ON) +option(CPPCHK_GLIBCXX_DEBUG "Usage of STL debug checks in Debug build" ON) option(USE_THREADS "Usage of threads instead of fork() for -j" OFF) option(USE_BOOST "Usage of Boost" OFF) +option(USE_LIBCXX "Use libc++ instead of libstdc++" OFF) option(DISABLE_CRTDBG_MAP_ALLOC "Disable usage of Visual Studio C++ memory leak detection in Debug build" OFF) option(NO_UNIX_SIGNAL_HANDLING "Disable usage of Unix Signal Handling" OFF) diff --git a/cmake/printInfo.cmake b/cmake/printInfo.cmake index 0cad74590cc..af51ce59989 100644 --- a/cmake/printInfo.cmake +++ b/cmake/printInfo.cmake @@ -76,6 +76,7 @@ if (USE_BOOST) message( STATUS "Boost_VERSION_STRING = ${Boost_VERSION_STRING}") message( STATUS "Boost_INCLUDE_DIRS = ${Boost_INCLUDE_DIRS}") endif() +message( STATUS "USE_LIBCXX = ${USE_LIBCXX}" ) message( STATUS ) if(${ANALYZE_ADDRESS}) From 7912e261251199ace85426c91984b5bdb18787ec Mon Sep 17 00:00:00 2001 From: firewave Date: Mon, 5 Dec 2022 13:53:35 +0100 Subject: [PATCH 17/17] testmathlib.cpp: adjustments for `libc++` --- test/testmathlib.cpp | 52 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/test/testmathlib.cpp b/test/testmathlib.cpp index b2c8711b21b..c651707e024 100644 --- a/test/testmathlib.cpp +++ b/test/testmathlib.cpp @@ -565,11 +565,17 @@ class TestMathLib : public TestFixture { } void toDoubleNumber() const { - ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1"), 0.001); - ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1f"), 0.001); - ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1F"), 0.001); - ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1l"), 0.001); - ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1L"), 0.001); + // float values + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1."), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.f"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.F"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.l"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.L"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0f"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0F"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0l"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0L"), 0.001); ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("0x1"), 0.001); ASSERT_EQUALS_DOUBLE(10.0, MathLib::toDoubleNumber("10"), 0.001); ASSERT_EQUALS_DOUBLE(1000.0, MathLib::toDoubleNumber("10E+2"), 0.001); @@ -583,11 +589,32 @@ class TestMathLib : public TestFixture { ASSERT_EQUALS_DOUBLE(100.0, MathLib::toDoubleNumber("1.0E+2"), 0.001); ASSERT_EQUALS_DOUBLE(1e+10, MathLib::toDoubleNumber("1.0E+10"), 1); - // TODO: needs to fail - //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ff"), 0.001); - //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1FF"), 0.001); - //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ll"), 0.001); - //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1LL"), 0.001); + // valid non-float values + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1l"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1L"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ll"), 0.001); + ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1LL"), 0.001); + // TODO: need to succeed + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1u"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1U"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ul"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1UL"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1ULL"), 0.001); + + // TODO: need to fail + // invalid values + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1f"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1F"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.ff"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.FF"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.ll"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0LL"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0ff"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0FF"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0ll"), 0.001); + //ASSERT_EQUALS_DOUBLE(1.0, MathLib::toDoubleNumber("1.0LL"), 0.001); ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E+0"), 0.000001); ASSERT_EQUALS_DOUBLE(0.0, MathLib::toDoubleNumber("0E-0"), 0.000001); @@ -625,8 +652,13 @@ class TestMathLib : public TestFixture { ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: invalid"); +#ifdef _LIBCPP_VERSION + ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1invalid"); + ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: conversion failed: 1.1invalid"); +#else ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1invalid"); ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1.1invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1.1invalid"); +#endif ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("1 invalid"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: 1 invalid"); ASSERT_THROW_EQUALS(MathLib::toDoubleNumber("-1e-08.0"), InternalError, "Internal Error. MathLib::toDoubleNumber: input was not completely consumed: -1e-08.0");