From 42c95037a1bc3a468a8d822b7622d658ac75a65d Mon Sep 17 00:00:00 2001 From: seelabs Date: Wed, 22 Feb 2023 11:58:36 -0500 Subject: [PATCH] [fold] Fix bug with all zero data; Expose and test detail functions --- src/ripple/protocol/impl/tokens.cpp | 52 +++++++-------- src/ripple/protocol/tokens.h | 22 ++++++ src/test/basics/base58_test.cpp | 100 ++++++++++++++++++++++++++-- 3 files changed, 139 insertions(+), 35 deletions(-) diff --git a/src/ripple/protocol/impl/tokens.cpp b/src/ripple/protocol/impl/tokens.cpp index 0ea0a68e45b..ed21ecb7d06 100644 --- a/src/ripple/protocol/impl/tokens.cpp +++ b/src/ripple/protocol/impl/tokens.cpp @@ -91,9 +91,31 @@ checksum(void* out, void const* message, std::size_t size) std::memcpy(out, h.data(), 4); } +[[nodiscard]] std::string +encodeBase58Token(TokenType type, void const* token, std::size_t size) +{ +#ifndef _MSC_VER + return b58_fast::encodeBase58Token(type, token, size); +#else + return b58_ref::encodeBase58Token(type, token, size); +#endif +} + +[[nodiscard]] std::string +decodeBase58Token(std::string const& s, TokenType type) +{ +#ifndef _MSC_VER + return b58_fast::decodeBase58Token(s, type); +#else + return b58_ref::decodeBase58Token_ms(s, type); +#endif +} + +namespace b58_ref { + namespace detail { -static std::string +std::string encodeBase58( void const* message, std::size_t size, @@ -144,7 +166,7 @@ encodeBase58( return str; } -static std::string +std::string decodeBase58(std::string const& s) { auto psz = reinterpret_cast(s.c_str()); @@ -193,27 +215,6 @@ decodeBase58(std::string const& s) } // namespace detail -[[nodiscard]] std::string -encodeBase58Token(TokenType type, void const* token, std::size_t size) -{ -#ifndef _MSC_VER - return b58_fast::encodeBase58Token(type, token, size); -#else - return b58_ref::encodeBase58Token(type, token, size); -#endif -} - -[[nodiscard]] std::string -decodeBase58Token(std::string const& s, TokenType type) -{ -#ifndef _MSC_VER - return b58_fast::decodeBase58Token(s, type); -#else - return b58_ref::decodeBase58Token_ms(s, type); -#endif -} - -namespace b58_ref { std::string encodeBase58Token(TokenType type, void const* token, std::size_t size) { @@ -478,11 +479,6 @@ b58_to_b256(std::string_view input, std::span out) for (int i = 0; i < 8; ++i) { std::uint8_t const b = (c >> (8 * (7 - i))) & 0xff; - if (i == 7) - { - // handle the all zero case - write the last zero - skip_zero = false; - } if (skip_zero) { if (b == 0) diff --git a/src/ripple/protocol/tokens.h b/src/ripple/protocol/tokens.h index 1f4e865ec24..d2a60af1379 100644 --- a/src/ripple/protocol/tokens.h +++ b/src/ripple/protocol/tokens.h @@ -78,6 +78,19 @@ encodeBase58Token(TokenType type, void const* token, std::size_t size); [[nodiscard]] std::string decodeBase58Token(std::string const& s, TokenType type); + +namespace detail { +// Expose detail functions for unit tests only +std::string +encodeBase58( + void const* message, + std::size_t size, + void* temp, + std::size_t temp_size); + +std::string +decodeBase58(std::string const& s); +} // namespace detail } // namespace b58_ref #ifndef _MSC_VER @@ -104,6 +117,15 @@ encodeBase58Token(TokenType type, void const* token, std::size_t size); [[nodiscard]] std::string decodeBase58Token(std::string const& s, TokenType type); +namespace detail { +// Expose detail functions for unit tests only +B58Result> +b256_to_b58(std::span input, std::span out); + +B58Result> +b58_to_b256(std::string_view input, std::span out); +} // namespace detail + } // namespace b58_fast #endif } // namespace ripple diff --git a/src/test/basics/base58_test.cpp b/src/test/basics/base58_test.cpp index 3cb520ed7a2..4f6c5a66f0c 100644 --- a/src/test/basics/base58_test.cpp +++ b/src/test/basics/base58_test.cpp @@ -238,15 +238,93 @@ class base58_test : public beast::unit_test::suite testFastMatchesRef() { testcase("fast_matches_ref"); - std::array b256DataBuf; - std::array b58ResultBuf[2]; - std::array, 2> b58Result; + auto testRawEncode = [&](std::span const& b256Data) { + std::array b58ResultBuf[2]; + std::array, 2> b58Result; - std::array b256ResultBuf[2]; - std::array, 2> b256Result; + std::array b256ResultBuf[2]; + std::array, 2> b256Result; + for (int i = 0; i < 2; ++i) + { + auto const outBuf = + std::span(b58ResultBuf[i].data(), b58ResultBuf[i].size()); + if (i == 0) + { + auto const r = + ripple::b58_fast::detail::b256_to_b58(b256Data, outBuf); + BEAST_EXPECT(r); + b58Result[i] = r.value(); + } + else + { + std::array tmpBuf; + auto const s = ripple::b58_ref::detail::encodeBase58( + b256Data.data(), + b256Data.size(), + tmpBuf.data(), + tmpBuf.size()); + BEAST_EXPECT(s.size()); + b58Result[i] = outBuf.subspan(0, s.size()); + std::copy(s.begin(), s.end(), b58Result[i].begin()); + } + } + if (BEAST_EXPECT(b58Result[0].size() == b58Result[1].size())) + { + if (!BEAST_EXPECT( + memcmp( + b58Result[0].data(), + b58Result[1].data(), + b58Result[0].size()) == 0)) + { + printAsChar(b58Result[0], b58Result[1]); + } + } - auto testIt = [&](ripple::TokenType const tokType, - std::span const& b256Data) { + for (int i = 0; i < 2; ++i) + { + auto const outBuf = + std::span(b256ResultBuf[i].data(), b256ResultBuf[i].size()); + if (i == 0) + { + std::string const in( + b58Result[i].data(), + b58Result[i].data() + b58Result[i].size()); + auto const r = + ripple::b58_fast::detail::b58_to_b256(in, outBuf); + BEAST_EXPECT(r); + b256Result[i] = r.value(); + } + else + { + std::string const st( + b58Result[i].begin(), b58Result[i].end()); + auto const s = ripple::b58_ref::detail::decodeBase58(st); + BEAST_EXPECT(s.size()); + b256Result[i] = outBuf.subspan(0, s.size()); + std::copy(s.begin(), s.end(), b256Result[i].begin()); + } + } + + if (BEAST_EXPECT(b256Result[0].size() == b256Result[1].size())) + { + if (!BEAST_EXPECT( + memcmp( + b256Result[0].data(), + b256Result[1].data(), + b256Result[0].size()) == 0)) + { + printAsInt(b256Result[0], b256Result[1]); + } + } + }; + + auto testTokenEncode = [&](ripple::TokenType const tokType, + std::span const& b256Data) { + std::array b58ResultBuf[2]; + std::array, 2> b58Result; + + std::array b256ResultBuf[2]; + std::array, 2> b256Result; for (int i = 0; i < 2; ++i) { auto const outBuf = @@ -318,10 +396,17 @@ class base58_test : public beast::unit_test::suite } }; + auto testIt = [&](ripple::TokenType const tokType, + std::span const& b256Data) { + testRawEncode(b256Data); + testTokenEncode(tokType, b256Data); + }; + // test every token type with data where every byte is the same and the // bytes range from 0-255 for (int i = 0; i < numTokenTypeIndexes; ++i) { + std::array b256DataBuf; auto const [tokType, tokSize] = tokenTypeAndSize(i); for (int d = 0; d < 255; ++d) { @@ -334,6 +419,7 @@ class base58_test : public beast::unit_test::suite constexpr std::size_t iters = 1000000; for (int i = 0; i < iters; ++i) { + std::array b256DataBuf; auto const [tokType, b256Data] = randomB256TestData( std::span(b256DataBuf.data(), b256DataBuf.size())); testIt(tokType, b256Data);