Skip to content

Commit c157816

Browse files
thejohnfreemanximinez
authored andcommitted
Use error codes throughout fast Base58 implementation
1 parent eba5d19 commit c157816

File tree

4 files changed

+75
-18
lines changed

4 files changed

+75
-18
lines changed

src/ripple/protocol/impl/b58_utils.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define RIPPLE_PROTOCOL_B58_UTILS_H_INCLUDED
2222

2323
#include <ripple/basics/contract.h>
24+
#include <ripple/protocol/impl/token_errors.h>
2425

2526
#include <boost/outcome.hpp>
2627
#include <boost/outcome/result.hpp>
@@ -71,12 +72,12 @@ carrying_add(std::uint64_t a, std::uint64_t b)
7172
// (i.e a[0] is the 2^0 coefficient, a[n] is the 2^(64*n) coefficient)
7273
// panics if overflows (this is a specialized adder for b58 decoding.
7374
// it should never overflow).
74-
inline void
75+
[[nodiscard]] inline TokenCodecErrc
7576
inplace_bigint_add(std::span<std::uint64_t> a, std::uint64_t b)
7677
{
7778
if (a.size() <= 1)
7879
{
79-
ripple::LogicError("Input span too small for inplace_bigint_add");
80+
return TokenCodecErrc::inputTooSmall;
8081
}
8182

8283
std::uint64_t carry;
@@ -86,28 +87,29 @@ inplace_bigint_add(std::span<std::uint64_t> a, std::uint64_t b)
8687
{
8788
if (!carry)
8889
{
89-
return;
90+
return TokenCodecErrc::success;
9091
}
9192
std::tie(v, carry) = carrying_add(v, 1);
9293
}
9394
if (carry)
9495
{
95-
LogicError("Overflow in inplace_bigint_add");
96+
return TokenCodecErrc::overflowAdd;
9697
}
98+
return TokenCodecErrc::success;
9799
}
98100

99-
inline void
101+
[[nodiscard]] inline TokenCodecErrc
100102
inplace_bigint_mul(std::span<std::uint64_t> a, std::uint64_t b)
101103
{
102104
if (a.empty())
103105
{
104-
LogicError("Empty span passed to inplace_bigint_mul");
106+
return TokenCodecErrc::inputTooSmall;
105107
}
106108

107109
auto const last_index = a.size() - 1;
108110
if (a[last_index] != 0)
109111
{
110-
LogicError("Non-zero element in inplace_bigint_mul last index");
112+
return TokenCodecErrc::inputTooLarge;
111113
}
112114

113115
std::uint64_t carry = 0;
@@ -116,7 +118,9 @@ inplace_bigint_mul(std::span<std::uint64_t> a, std::uint64_t b)
116118
std::tie(coeff, carry) = carrying_mul(coeff, b, carry);
117119
}
118120
a[last_index] = carry;
121+
return TokenCodecErrc::success;
119122
}
123+
120124
// divide a "big uint" value inplace and return the mod
121125
// numerator is stored so smallest coefficients come first
122126
[[nodiscard]] inline std::uint64_t
@@ -166,11 +170,7 @@ inplace_bigint_div_rem(std::span<uint64_t> numerator, std::uint64_t divisor)
166170
b58_10_to_b58_be(std::uint64_t input)
167171
{
168172
constexpr std::uint64_t B_58_10 = 430804206899405824; // 58^10;
169-
if (input >= B_58_10)
170-
{
171-
LogicError("Input to b58_10_to_b58_be equals or exceeds 58^10.");
172-
}
173-
173+
assert(input < B_58_10);
174174
constexpr std::size_t resultSize = 10;
175175
std::array<std::uint8_t, resultSize> result{};
176176
int i = 0;

src/ripple/protocol/impl/token_errors.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum class TokenCodecErrc {
3232
mismatchedTokenType,
3333
mismatchedChecksum,
3434
invalidEncodingChar,
35+
overflowAdd,
3536
unknown,
3637
};
3738
}

src/ripple/protocol/impl/tokens.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,11 @@ b256_to_b58_be(std::span<std::uint8_t const> input, std::span<std::uint8_t> out)
467467
{
468468
continue;
469469
}
470+
static constexpr std::uint64_t B_58_10 = 430804206899405824; // 58^10;
471+
if (base_58_10_coeff[i] >= B_58_10)
472+
{
473+
return Unexpected(TokenCodecErrc::inputTooLarge);
474+
}
470475
std::array<std::uint8_t, 10> const b58_be =
471476
ripple::b58_fast::detail::b58_10_to_b58_be(base_58_10_coeff[i]);
472477
std::size_t to_skip = 0;
@@ -565,10 +570,23 @@ b58_to_b256_be(std::string_view input, std::span<std::uint8_t> out)
565570
for (int i = 1; i < num_b_58_10_coeffs; ++i)
566571
{
567572
std::uint64_t const c = b_58_10_coeff[i];
568-
ripple::b58_fast::detail::inplace_bigint_mul(
569-
std::span(&result[0], cur_result_size + 1), B_58_10);
570-
ripple::b58_fast::detail::inplace_bigint_add(
571-
std::span(&result[0], cur_result_size + 1), c);
573+
574+
{
575+
auto code = ripple::b58_fast::detail::inplace_bigint_mul(
576+
std::span(&result[0], cur_result_size + 1), B_58_10);
577+
if (code != TokenCodecErrc::success)
578+
{
579+
return Unexpected(code);
580+
}
581+
}
582+
{
583+
auto code = ripple::b58_fast::detail::inplace_bigint_add(
584+
std::span(&result[0], cur_result_size + 1), c);
585+
if (code != TokenCodecErrc::success)
586+
{
587+
return Unexpected(code);
588+
}
589+
}
572590
if (result[cur_result_size] != 0)
573591
{
574592
cur_result_size += 1;

src/test/basics/base58_test.cpp

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ class base58_test : public beast::unit_test::suite
177177
constexpr std::size_t iters = 100000;
178178
auto eng = randEngine();
179179
std::uniform_int_distribution<std::uint64_t> dist;
180+
std::uniform_int_distribution<std::uint64_t> dist1(1);
180181
for (int i = 0; i < iters; ++i)
181182
{
182183
std::uint64_t const d = dist(eng);
@@ -209,12 +210,31 @@ class base58_test : public beast::unit_test::suite
209210

210211
auto const refAdd = boostBigInt + d;
211212

212-
b58_fast::detail::inplace_bigint_add(
213+
auto const result = b58_fast::detail::inplace_bigint_add(
213214
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
215+
BEAST_EXPECT(result == TokenCodecErrc::success);
214216
auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
215217
BEAST_EXPECT(refAdd == foundAdd);
216218
}
217219
for (int i = 0; i < iters; ++i)
220+
{
221+
std::uint64_t const d = dist1(eng);
222+
// Force overflow
223+
std::vector<std::uint64_t> bigInt(
224+
5, std::numeric_limits<std::uint64_t>::max());
225+
226+
auto const boostBigInt = multiprecision_utils::toBoostMP(
227+
std::span<std::uint64_t>(bigInt.data(), bigInt.size()));
228+
229+
auto const refAdd = boostBigInt + d;
230+
231+
auto const result = b58_fast::detail::inplace_bigint_add(
232+
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
233+
BEAST_EXPECT(result == TokenCodecErrc::overflowAdd);
234+
auto const foundAdd = multiprecision_utils::toBoostMP(bigInt);
235+
BEAST_EXPECT(refAdd != foundAdd);
236+
}
237+
for (int i = 0; i < iters; ++i)
218238
{
219239
std::uint64_t const d = dist(eng);
220240
auto bigInt = multiprecision_utils::randomBigInt(/* minSize */ 2);
@@ -226,11 +246,29 @@ class base58_test : public beast::unit_test::suite
226246

227247
auto const refMul = boostBigInt * d;
228248

229-
b58_fast::detail::inplace_bigint_mul(
249+
auto const result = b58_fast::detail::inplace_bigint_mul(
230250
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
251+
BEAST_EXPECT(result == TokenCodecErrc::success);
231252
auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
232253
BEAST_EXPECT(refMul == foundMul);
233254
}
255+
for (int i = 0; i < iters; ++i)
256+
{
257+
std::uint64_t const d = dist1(eng);
258+
// Force overflow
259+
std::vector<std::uint64_t> bigInt(
260+
5, std::numeric_limits<std::uint64_t>::max());
261+
auto const boostBigInt = multiprecision_utils::toBoostMP(
262+
std::span<std::uint64_t>(bigInt.data(), bigInt.size()));
263+
264+
auto const refMul = boostBigInt * d;
265+
266+
auto const result = b58_fast::detail::inplace_bigint_mul(
267+
std::span<uint64_t>(bigInt.data(), bigInt.size()), d);
268+
BEAST_EXPECT(result == TokenCodecErrc::inputTooLarge);
269+
auto const foundMul = multiprecision_utils::toBoostMP(bigInt);
270+
BEAST_EXPECT(refMul != foundMul);
271+
}
234272
}
235273

236274
void

0 commit comments

Comments
 (0)