From fac01888d17423d6c23a9ce15d98fc88fb34e3cc Mon Sep 17 00:00:00 2001 From: MarcoFalke Date: Tue, 2 Nov 2021 09:48:10 +0100 Subject: Move AdditionOverflow to util, Add CheckedAdd with unit tests --- src/Makefile.am | 1 + src/test/fuzz/addition_overflow.cpp | 1 + src/test/fuzz/crypto_chacha20_poly1305_aead.cpp | 1 + src/test/fuzz/integer.cpp | 1 + src/test/fuzz/pow.cpp | 1 + src/test/fuzz/util.cpp | 1 + src/test/fuzz/util.h | 11 --------- src/test/util_tests.cpp | 33 +++++++++++++++++++++++++ src/util/overflow.h | 31 +++++++++++++++++++++++ 9 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 src/util/overflow.h diff --git a/src/Makefile.am b/src/Makefile.am index 4199f7e89d..994038a03b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -248,6 +248,7 @@ BITCOIN_CORE_H = \ util/macros.h \ util/message.h \ util/moneystr.h \ + util/overflow.h \ util/overloaded.h \ util/rbf.h \ util/readwritefile.h \ diff --git a/src/test/fuzz/addition_overflow.cpp b/src/test/fuzz/addition_overflow.cpp index c6cfbd8d30..cfad41659e 100644 --- a/src/test/fuzz/addition_overflow.cpp +++ b/src/test/fuzz/addition_overflow.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp index 5e60b0f25b..596614a71b 100644 --- a/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp +++ b/src/test/fuzz/crypto_chacha20_poly1305_aead.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/src/test/fuzz/integer.cpp b/src/test/fuzz/integer.cpp index ce424c443e..4999d87f9d 100644 --- a/src/test/fuzz/integer.cpp +++ b/src/test/fuzz/integer.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/src/test/fuzz/pow.cpp b/src/test/fuzz/pow.cpp index 1123c8c170..0004d82d66 100644 --- a/src/test/fuzz/pow.cpp +++ b/src/test/fuzz/pow.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include diff --git a/src/test/fuzz/util.cpp b/src/test/fuzz/util.cpp index 843b29b911..5520eee758 100644 --- a/src/test/fuzz/util.cpp +++ b/src/test/fuzz/util.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include diff --git a/src/test/fuzz/util.h b/src/test/fuzz/util.h index 7937315822..f4f8e9e70d 100644 --- a/src/test/fuzz/util.h +++ b/src/test/fuzz/util.h @@ -193,17 +193,6 @@ template } } -template -[[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept -{ - static_assert(std::is_integral::value, "Integral required."); - if (std::numeric_limits::is_signed) { - return (i > 0 && j > std::numeric_limits::max() - i) || - (i < 0 && j < std::numeric_limits::min() - i); - } - return std::numeric_limits::max() - i < j; -} - [[nodiscard]] bool ContainsSpentInput(const CTransaction& tx, const CCoinsViewCache& inputs) noexcept; /** diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 9540cead24..bc3ef9f7f1 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -15,6 +15,7 @@ #include #include // For MessageSign(), MessageVerify(), MESSAGE_MAGIC #include +#include #include #include #include @@ -1463,6 +1464,38 @@ BOOST_AUTO_TEST_CASE(test_IsDigit) BOOST_CHECK_EQUAL(IsDigit(9), false); } +/* Check for overflow */ +template +static void TestAddMatrixOverflow() +{ + constexpr T MAXI{std::numeric_limits::max()}; + BOOST_CHECK(!CheckedAdd(T{1}, MAXI)); + BOOST_CHECK(!CheckedAdd(MAXI, MAXI)); + BOOST_CHECK_EQUAL(0, CheckedAdd(T{0}, T{0}).value()); + BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{0}, MAXI).value()); + BOOST_CHECK_EQUAL(MAXI, CheckedAdd(T{1}, MAXI - 1).value()); +} + +/* Check for overflow or underflow */ +template +static void TestAddMatrix() +{ + TestAddMatrixOverflow(); + constexpr T MINI{std::numeric_limits::min()}; + constexpr T MAXI{std::numeric_limits::max()}; + BOOST_CHECK(!CheckedAdd(T{-1}, MINI)); + BOOST_CHECK(!CheckedAdd(MINI, MINI)); + BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{0}, MINI).value()); + BOOST_CHECK_EQUAL(MINI, CheckedAdd(T{-1}, MINI + 1).value()); + BOOST_CHECK_EQUAL(-1, CheckedAdd(MINI, MAXI).value()); +} + +BOOST_AUTO_TEST_CASE(util_overflow) +{ + TestAddMatrixOverflow(); + TestAddMatrix(); +} + BOOST_AUTO_TEST_CASE(test_ParseInt32) { int32_t n; diff --git a/src/util/overflow.h b/src/util/overflow.h new file mode 100644 index 0000000000..5982af8d04 --- /dev/null +++ b/src/util/overflow.h @@ -0,0 +1,31 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_OVERFLOW_H +#define BITCOIN_UTIL_OVERFLOW_H + +#include +#include + +template +[[nodiscard]] bool AdditionOverflow(const T i, const T j) noexcept +{ + static_assert(std::is_integral::value, "Integral required."); + if (std::numeric_limits::is_signed) { + return (i > 0 && j > std::numeric_limits::max() - i) || + (i < 0 && j < std::numeric_limits::min() - i); + } + return std::numeric_limits::max() - i < j; +} + +template +[[nodiscard]] std::optional CheckedAdd(const T i, const T j) noexcept +{ + if (AdditionOverflow(i, j)) { + return std::nullopt; + } + return i + j; +} + +#endif // BITCOIN_UTIL_OVERFLOW_H -- cgit v1.2.3