From c8511dfc075ffee615c885c8591400ac5a4675d8 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 7 Jun 2018 15:30:44 +1200 Subject: [PATCH] Fix bech32::Encode() error handling Previously, an input with invalid characters would result in out-of-bounds reads, potentially exposing up to 224 bytes of memory following the location of the CHARSET constant. This commit fixes the function to return an empty string, which is what was originally documented as happening. --- src/bech32.cpp | 3 +++ src/test/bech32_tests.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/bech32.cpp b/src/bech32.cpp index 573eac58b..2889f8f99 100644 --- a/src/bech32.cpp +++ b/src/bech32.cpp @@ -150,6 +150,9 @@ std::string Encode(const std::string& hrp, const data& values) { std::string ret = hrp + '1'; ret.reserve(ret.size() + combined.size()); for (auto c : combined) { + if (c >= 32) { + return ""; + } ret += CHARSET[c]; } return ret; diff --git a/src/test/bech32_tests.cpp b/src/test/bech32_tests.cpp index ce4cddd64..f71ca1bf2 100644 --- a/src/test/bech32_tests.cpp +++ b/src/test/bech32_tests.cpp @@ -64,4 +64,37 @@ BOOST_AUTO_TEST_CASE(bip173_testvectors_invalid) } } +BOOST_AUTO_TEST_CASE(bech32_deterministic_valid) +{ + for (size_t i = 0; i < 255; i++) { + std::vector input(32, i); + auto encoded = bech32::Encode("a", input); + if (i < 32) { + // Valid input + BOOST_CHECK(!encoded.empty()); + auto ret = bech32::Decode(encoded); + BOOST_CHECK(ret.first == "a"); + BOOST_CHECK(ret.second == input); + } else { + // Invalid input + BOOST_CHECK(encoded.empty()); + } + } + + for (size_t i = 0; i < 255; i++) { + std::vector input(43, i); + auto encoded = bech32::Encode("a", input); + if (i < 32) { + // Valid input + BOOST_CHECK(!encoded.empty()); + auto ret = bech32::Decode(encoded); + BOOST_CHECK(ret.first == "a"); + BOOST_CHECK(ret.second == input); + } else { + // Invalid input + BOOST_CHECK(encoded.empty()); + } + } +} + BOOST_AUTO_TEST_SUITE_END()