Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
74d554e
testmathlib.cpp: split `toULongNumber` into separate test case
firewave Dec 4, 2022
d71e86d
testmathlib.cpp: aligned tests in `toLongNumber` and `toULongNumber`
firewave Dec 4, 2022
32bcbc8
mathlib.cpp: fixed handling of negative binary numbers in `toULongNum…
firewave Dec 4, 2022
1eff4f1
mathlib.cpp: added handling of `std::invalid_argument` to `std::stoul…
firewave Dec 4, 2022
5b3ff5e
mathlib.cpp: added missing handling of char literals to `toULongNumbe…
firewave Dec 4, 2022
1114b90
testmathlib.cpp: check exception messages
firewave Dec 4, 2022
2dd2dfa
testmathlib.cpp: added tests which produce `std::invalid_argument` ex…
firewave Dec 4, 2022
e7edc7b
MathLib: removed pointless info from `to{U}LongNumber()` exception me…
firewave Dec 5, 2022
5553908
fixed #10695 - make sure the whole input is being consumed in `MathLi…
firewave Dec 5, 2022
f40781b
mathlib.cpp: use `toDoubleNumber()` in `toULongNumber()` as well
firewave Dec 5, 2022
708162a
MathLib: improved handling of invalid input in `toDoubleNumber()` / i…
firewave Dec 5, 2022
42bc53b
ubsan.yml: added `report_error_type=1` to `UBSAN_OPTIONS`
firewave Dec 5, 2022
80522d9
mathlib.cpp: fixed UBSAN warning about negative double being out-of-r…
firewave Dec 5, 2022
1c36cde
MathLib: fixed incorrect `toString()` result if it contains an exponent
firewave Dec 5, 2022
91b1233
mathlib.cpp: avoid unnecessary copies in `toString()`
firewave Dec 5, 2022
0927ad4
added CMake option `USE_LIBCXX` to use `libc++` instead of `libstdc++…
firewave Dec 5, 2022
7912e26
testmathlib.cpp: adjustments for `libc++`
firewave Dec 5, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ubsan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 8 additions & 4 deletions cmake/compilerDefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
5 changes: 5 additions & 0 deletions cmake/compileroptions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion cmake/options.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions cmake/printInfo.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down
88 changes: 62 additions & 26 deletions lib/mathlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +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::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);
}
}

Expand All @@ -303,8 +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::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);
}
}

Expand All @@ -318,26 +322,38 @@ 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;
}

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<biguint>::max())
return std::numeric_limits<biguint>::max();
else
return static_cast<biguint>(doubleval);
else // cast to bigint to avoid UBSAN warning about negative double being out-of-range
return static_cast<biguint>(static_cast<bigint>(doubleval));
}

if (isCharLiteral(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 + " (" + 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);
}
}

Expand All @@ -355,8 +371,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::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);
}
}

Expand All @@ -365,8 +383,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::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);
}
}

Expand All @@ -388,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<bigint>::max())
return std::numeric_limits<bigint>::max();
Expand All @@ -401,10 +422,18 @@ 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 + " (" + 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);
}
}

Expand Down Expand Up @@ -463,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))
Expand All @@ -479,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;
}

Expand All @@ -488,11 +523,12 @@ template<> std::string MathLib::toString<double>(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('.') == 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)
Expand Down
Loading