This is an automated email from the ASF dual-hosted git repository. garydgregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-codec.git
commit d106a40cae3db465cbfb3d22f05dbb96cdd90153 Author: Gary Gregory <[email protected]> AuthorDate: Fri Sep 18 05:09:57 2026 -0700 Limit Base58 decoding input length Add a configurable 8192-byte default limit and reject oversized input before buffering or conversion. Cover stream boundaries and overflow checks, update large-input tests, and document the limit and configuration options. --- src/changes/changes.xml | 1 + .../org/apache/commons/codec/binary/Base58.java | 72 +++++++- .../commons/codec/binary/Base58InputStream.java | 35 ++-- .../commons/codec/binary/Base58OutputStream.java | 41 ++--- .../codec/binary/Base58MaxDecodeLengthTest.java | 181 +++++++++++++++++++++ .../apache/commons/codec/binary/Base58Test.java | 6 +- 6 files changed, 276 insertions(+), 60 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 76545139..9a311b3b 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -55,6 +55,7 @@ The <action> type attribute can be add,update,fix,remove. <action type="fix" dev="ggregory" due-to="Gary Gregory">Throw DecoderException instead of IllegalArgumentException in RFC1522Codec.decodeText(String).</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">Fix Blake3 KDF example and clarify finalization semantics.</action> <action type="fix" dev="ggregory" due-to="Gary Gregory">Base32 and Base64 STRICT decoding now require the encoder's canonical alphabet, padding, and line separators, and validate streams through EOF. Use LENIENT to retain permissive decoding.</action> + <action type="fix" dev="ggregory" due-to="Gary Gregory">Limit Base58 decoding to 8192 encoded bytes by default, checking cumulative stream input before buffering. Use Base58.Builder.setMaxDecodeLength(int) for larger trusted input. Encoding remains unlimited.</action> <!-- ADD --> <action type="add" dev="ggregory" due-to="Gary Gregory">Add and use PhoneticEngine.Builder and deprecate old constructors.</action> <action type="add" dev="ggregory" due-to="Gary Gregory">Add BeiderMorseEncoder.Builder and deprecate old constructor.</action> diff --git a/src/main/java/org/apache/commons/codec/binary/Base58.java b/src/main/java/org/apache/commons/codec/binary/Base58.java index 126a9b64..acbeebf1 100644 --- a/src/main/java/org/apache/commons/codec/binary/Base58.java +++ b/src/main/java/org/apache/commons/codec/binary/Base58.java @@ -28,8 +28,12 @@ import java.util.function.BiConsumer; * commonly used in Bitcoin and other blockchain systems. * </p> * <p> - * This implementation accumulates data internally until EOF is signaled, at which point the entire input is converted using BigInteger arithmetic. This is - * necessary because Base58 encoding/decoding requires access to the complete data to properly handle leading zeros. + * Encoding and decoding produce results when EOF is signaled. + * </p> + * <p> + * Decoding rejects input longer than a configurable maximum ({@link #DEFAULT_MAX_DECODE_LENGTH} encoded bytes by default, see + * {@link Builder#setMaxDecodeLength(int)}). Encoding is not limited: callers should bound untrusted binary input before encoding. Encoded output + * can exceed the default decode limit; raise the limit explicitly when decoding larger trusted values. * </p> * <p> * This class is thread-safe for read operations but the Context object used during encoding/decoding should not be shared between threads. @@ -57,6 +61,8 @@ public class Base58 extends BaseNCodec { */ public static class Builder extends AbstractBuilder<Base58, Builder> { + private int maxDecodeLength = DEFAULT_MAX_DECODE_LENGTH; + /** * Constructs a new Base58 builder. */ @@ -75,6 +81,10 @@ public class Base58 extends BaseNCodec { return new Base58(this); } + int getMaxDecodeLength() { + return maxDecodeLength; + } + /** * Sets the encode table and derives the matching decode table. * @@ -87,12 +97,41 @@ public class Base58 extends BaseNCodec { super.setDecodeTableRaw(toDecodeTable(encodeTable)); return super.setEncodeTable(encodeTable); } + + /** + * Sets the maximum number of encoded bytes accepted by a single decode operation. + * <p> + * Defaults to {@link Base58#DEFAULT_MAX_DECODE_LENGTH}. Pass {@link Integer#MAX_VALUE} to effectively disable the limit for trusted input. + * </p> + * + * @param maxDecodeLength The maximum accepted encoded input length; must be positive. + * @return {@code this} instance. + * @throws IllegalArgumentException if maxDecodeLength is not positive. + * @since 1.23.0 + */ + public Builder setMaxDecodeLength(final int maxDecodeLength) { + if (maxDecodeLength <= 0) { + throw new IllegalArgumentException("maxDecodeLength must be positive."); + } + this.maxDecodeLength = maxDecodeLength; + return this; + } } private static final BigInteger BASE = BigInteger.valueOf(58); private static final int DECODING_TABLE_LENGTH = 256; private static final int ENCODING_TABLE_LENGTH = 58; + /** + * The default maximum number of encoded bytes accepted by a single decode operation: {@value}. + * <p> + * Use {@link Builder#setMaxDecodeLength(int)} to raise (or effectively disable) the limit for trusted input. + * </p> + * + * @since 1.23.0 + */ + public static final int DEFAULT_MAX_DECODE_LENGTH = 8192; + /** * Base58 alphabet: 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz * (excludes: 0, I, O, l). @@ -179,6 +218,11 @@ public class Base58 extends BaseNCodec { return calculateDecodeTable(table); } + /** + * The maximum number of encoded bytes accepted by a single decode operation. + */ + private final int maxDecodeLength; + /** * Constructs a Base58 codec used for encoding and decoding. */ @@ -193,6 +237,14 @@ public class Base58 extends BaseNCodec { */ public Base58(final Builder builder) { super(builder); + this.maxDecodeLength = builder.getMaxDecodeLength(); + } + + private void checkDecodeLength(final int length, final int accumulatedLength) { + if (length > maxDecodeLength - accumulatedLength) { + throw new IllegalArgumentException("Base58 input exceeds the maximum decode length of " + maxDecodeLength + + " bytes; use Base58.Builder.setMaxDecodeLength(int) to raise the limit."); + } } private void code(final byte[] array, final int offset, final int length, final Context context, final BiConsumer<byte[], Context> consumer) { @@ -221,8 +273,8 @@ public class Base58 extends BaseNCodec { * <p> * Uses 32-bit word arithmetic ({@code int[]} with {@code long} carry) to convert the Base58 string to binary data, avoiding {@link BigInteger} and its * per-digit object allocation. Each Base58 digit is processed left-to-right using Horner's scheme: {@code value = value * 58 + digit}. An - * {@code wordsStart} cursor tracks the leftmost word that contains data, so the inner loop only touches the active portion of the work buffer — the active - * range grows by at most one word per four digits (since log(58)/log(256) < 1), keeping total work well below {@code inputLength²}. + * {@code wordsStart} cursor tracks the leftmost word that contains data, so the inner loop only touches the active portion of the work buffer. The active + * range grows linearly with the number of digits, so total conversion work is quadratic in the input length. * </p> * <p> * At each word position the carry satisfies {@code carry ≤ 57 + 58 × (2³²−1) < 2⁴⁰}, which fits in a Java {@code long}. @@ -233,9 +285,10 @@ public class Base58 extends BaseNCodec { * * @param base58 The Base58 encoded data. * @param context The context for this decoding operation. - * @throws IllegalArgumentException if the Base58 data contains invalid characters. + * @throws IllegalArgumentException if the Base58 data contains invalid characters or is longer than the configured maximum decode length. */ private void convertFromBase58(final byte[] base58, final Context context) { + checkDecodeLength(base58.length, 0); final int zero = encodeTable[0] & 0xff; // Count leading Base58 "zero" characters; each represents a leading zero byte in the output. int leadingZeros = 0; @@ -245,8 +298,10 @@ public class Base58 extends BaseNCodec { } leadingZeros++; } - // Instead of using BigInteger instances, we use a 32-bit word array. - // This provides ~4x speedup and avoids per-digit object allocation. + // Horner's scheme uses 32-bit words and a long carry, avoiding per-digit BigInteger allocation. + // wordsStart tracks the active word range, which grows linearly with the number of digits. + // Traversing this range for each digit makes conversion quadratic in the input length. + // At each word, carry <= 57 + 58 * (2^32 - 1) < 2^40, which fits in a long. // // Work buffer of 32-bit words, big-endian, right-aligned. // Upper bound on decoded bytes is base58.length, so (base58.length+3)/4 words suffice. @@ -331,6 +386,9 @@ public class Base58 extends BaseNCodec { */ @Override void decode(final byte[] array, final int offset, final int length, final Context context) { + if (!context.eof && length > 0) { + checkDecodeLength(length, context.buffer != null ? context.buffer.length : 0); + } code(array, offset, length, context, this::convertFromBase58); } diff --git a/src/main/java/org/apache/commons/codec/binary/Base58InputStream.java b/src/main/java/org/apache/commons/codec/binary/Base58InputStream.java index e6988214..1df56ea0 100644 --- a/src/main/java/org/apache/commons/codec/binary/Base58InputStream.java +++ b/src/main/java/org/apache/commons/codec/binary/Base58InputStream.java @@ -20,29 +20,18 @@ package org.apache.commons.codec.binary; import java.io.InputStream; /** - * Provides Base58 decoding in a streaming fashion (unlimited size). When encoding the default lineLength is 76 characters and the default lineEnding is CRLF, - * but these can be overridden by using the appropriate constructor. - * <p> - * The default behavior of the Base58InputStream is to DECODE, whereas the default behavior of the Base58OutputStream is to ENCODE, but this behavior can be - * overridden by using a different constructor. - * </p> - * <p> - * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode character encodings which are - * compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc). - * </p> - * <p> - * You can set the decoding behavior when the input bytes contain leftover trailing bits that cannot be created by a valid encoding. These can be bits that are - * unused from the final character or entire characters. The default mode is lenient decoding. - * </p> - * <ul> - * <li>Lenient: Any trailing bits are composed into 8-bit bytes where possible. The remainder are discarded.</li> - * <li>Strict: The decoding will throw an {@link IllegalArgumentException} if trailing bits are not part of a valid encoding. Any unused bits from the final - * character must be zero. Impossible counts of entire final characters are not allowed.</li> - * </ul> - * <p> - * When strict decoding is enabled it is expected that the decoded bytes will be re-encoded to a byte array that matches the original, i.e. no changes occur on - * the final character. This requires that the input bytes use the same padding and alphabet as the encoder. - * </p> + * Provides Base58 decoding through a stream interface. + * + * <p>The default behavior of Base58InputStream is to decode, and the default behavior of Base58OutputStream is to encode. The builder can select either + * behavior with {@code setEncode(boolean)}.</p> + * + * <p>Results are available only after EOF. Decoding accepts at most + * {@link Base58#DEFAULT_MAX_DECODE_LENGTH} encoded bytes by default and throws {@link java.io.IOException} when an input chunk would exceed the cumulative + * limit. To configure the limit, pass a codec built with {@link Base58.Builder#setMaxDecodeLength(int)} to the stream builder's + * {@code setBaseNCodec(Base58)} method.</p> + * + * <p>Encoding has no input limit. Callers should bound untrusted binary input before encoding, and explicitly raise the decode limit when decoding larger + * trusted values. Encoded output can exceed the default decode limit.</p> * * @see Base58 * @see <a href="https://datatracker.ietf.org/doc/html/draft-msporny-base58-03">The Base58 Encoding Scheme draft-msporny-base58-03</a> diff --git a/src/main/java/org/apache/commons/codec/binary/Base58OutputStream.java b/src/main/java/org/apache/commons/codec/binary/Base58OutputStream.java index bca12916..2d8d28e2 100644 --- a/src/main/java/org/apache/commons/codec/binary/Base58OutputStream.java +++ b/src/main/java/org/apache/commons/codec/binary/Base58OutputStream.java @@ -20,33 +20,20 @@ package org.apache.commons.codec.binary; import java.io.OutputStream; /** - * Provides Base58 encoding in a streaming fashion (unlimited size). When encoding the default lineLength is 76 characters and the default lineEnding is CRLF, - * but these can be overridden by using the appropriate constructor. - * <p> - * The default behavior of the Base58OutputStream is to ENCODE, whereas the default behavior of the Base58InputStream is to DECODE. But this behavior can be - * overridden by using a different constructor. - * </p> - * <p> - * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode character encodings which are - * compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc). - * </p> - * <p> - * <strong>Note:</strong> It is mandatory to close the stream after the last byte has been written to it, otherwise the final padding will be omitted and the - * resulting data will be incomplete/inconsistent. - * </p> - * <p> - * You can set the decoding behavior when the input bytes contain leftover trailing bits that cannot be created by a valid encoding. These can be bits that are - * unused from the final character or entire characters. The default mode is lenient decoding. - * </p> - * <ul> - * <li>Lenient: Any trailing bits are composed into 8-bit bytes where possible. The remainder are discarded.</li> - * <li>Strict: The decoding will throw an {@link IllegalArgumentException} if trailing bits are not part of a valid encoding. Any unused bits from the final - * character must be zero. Impossible counts of entire final characters are not allowed.</li> - * </ul> - * <p> - * When strict decoding is enabled it is expected that the decoded bytes will be re-encoded to a byte array that matches the original, i.e. no changes occur on - * the final character. This requires that the input bytes use the same padding and alphabet as the encoder. - * </p> + * Provides Base58 encoding through a stream interface. + * + * <p>The default behavior of Base58InputStream is to decode, and the default behavior of Base58OutputStream is to encode. The builder can select either + * behavior with {@code setEncode(boolean)}.</p> + * + * <p>Results are available only after EOF. Decoding accepts at most + * {@link Base58#DEFAULT_MAX_DECODE_LENGTH} encoded bytes by default and throws {@link java.io.IOException} when an input chunk would exceed the cumulative + * limit. To configure the limit, pass a codec built with {@link Base58.Builder#setMaxDecodeLength(int)} to the stream builder's + * {@code setBaseNCodec(Base58)} method.</p> + * + * <p>Encoding has no input limit. Callers should bound untrusted binary input before encoding, and explicitly raise the decode limit when decoding larger + * trusted values. Encoded output can exceed the default decode limit.</p> + * + * <p>Close the output stream or call {@link #eof()} after the last write to complete conversion.</p> * * @see Base58 * @see <a href="https://datatracker.ietf.org/doc/html/draft-msporny-base58-03">The Base58 Encoding Scheme draft-msporny-base58-03</a> diff --git a/src/test/java/org/apache/commons/codec/binary/Base58MaxDecodeLengthTest.java b/src/test/java/org/apache/commons/codec/binary/Base58MaxDecodeLengthTest.java new file mode 100644 index 00000000..149c55a8 --- /dev/null +++ b/src/test/java/org/apache/commons/codec/binary/Base58MaxDecodeLengthTest.java @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.codec.binary; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +/** + * Tests the maximum decode length limit that bounds the quadratic-cost Base58 decode against oversized untrusted input. + */ +class Base58MaxDecodeLengthTest { + + private static byte[] ones(final int length) { + final byte[] bytes = new byte[length]; + // '1' encodes a leading zero byte, so decoding stays cheap regardless of length. + Arrays.fill(bytes, (byte) '1'); + return bytes; + } + + @Test + void testConfiguredLimit() { + final Base58 small = Base58.builder().setMaxDecodeLength(10).get(); + assertThrows(IllegalArgumentException.class, () -> small.decode(ones(11))); + assertEquals(10, small.decode(ones(10)).length); + final Base58 unlimited = Base58.builder().setMaxDecodeLength(Integer.MAX_VALUE).get(); + assertEquals(Base58.DEFAULT_MAX_DECODE_LENGTH + 1, unlimited.decode(ones(Base58.DEFAULT_MAX_DECODE_LENGTH + 1)).length); + } + + @Test + void testDecodeAtLimitAccepted() { + assertEquals(Base58.DEFAULT_MAX_DECODE_LENGTH, new Base58().decode(ones(Base58.DEFAULT_MAX_DECODE_LENGTH)).length); + } + + @Test + void testDecodeOverLimitRejected() { + assertThrows(IllegalArgumentException.class, () -> new Base58().decode(ones(Base58.DEFAULT_MAX_DECODE_LENGTH + 1))); + } + + @Test + void testDefaultStreamsRejectOversizedInput() throws IOException { + final byte[] encoded = ones(Base58.DEFAULT_MAX_DECODE_LENGTH + 1); + try (Base58InputStream stream = new Base58InputStream(new ByteArrayInputStream(encoded))) { + assertThrows(IOException.class, stream::read); + } + try (Base58OutputStream stream = Base58OutputStream.builder().setOutputStream(new ByteArrayOutputStream()).setEncode(false).get()) { + assertThrows(IOException.class, () -> stream.write(encoded)); + } + } + + @Test + void testEncodingMayExceedDecodeLimit() throws IOException { + final byte[] input = new byte[Base58.DEFAULT_MAX_DECODE_LENGTH + 1]; + final Base58 codec = new Base58(); + final byte[] encoded = codec.encode(input); + assertEquals(input.length, encoded.length); + assertThrows(IllegalArgumentException.class, () -> codec.decode(encoded)); + final ByteArrayOutputStream sink = new ByteArrayOutputStream(); + try (Base58OutputStream stream = new Base58OutputStream(sink)) { + stream.write(input); + } + assertArrayEquals(encoded, sink.toByteArray()); + try (Base58InputStream stream = Base58InputStream.builder().setByteArray(input).setEncode(true).get()) { + assertArrayEquals(encoded, IOUtils.toByteArray(stream)); + } + final ByteArrayOutputStream decoded = new ByteArrayOutputStream(); + try (Base58OutputStream stream = Base58OutputStream.builder().setOutputStream(decoded).setEncode(false) + .setBaseNCodec(Base58.builder().setMaxDecodeLength(encoded.length).get()).get()) { + stream.write(encoded); + } + assertArrayEquals(input, decoded.toByteArray()); + } + + @ParameterizedTest + @ValueSource(ints = { 10, Base58.DEFAULT_MAX_DECODE_LENGTH, Base58.DEFAULT_MAX_DECODE_LENGTH + 1 }) + void testInputStreamAtConfiguredLimit(final int limit) throws IOException { + try (Base58InputStream stream = Base58InputStream.builder().setByteArray(ones(limit)).setBaseNCodec(Base58.builder().setMaxDecodeLength(limit).get()) + .get()) { + assertArrayEquals(new byte[limit], IOUtils.toByteArray(stream)); + } + } + + @Test + void testInputStreamRejectsBeforeEof() throws IOException { + final ByteArrayInputStream source = new ByteArrayInputStream(ones(100)) { + + @Override + public synchronized int read(final byte[] bytes, final int offset, final int length) { + return super.read(bytes, offset, Math.min(length, 3)); + } + }; + try (Base58InputStream stream = Base58InputStream.builder().setInputStream(source).setBaseNCodec(Base58.builder().setMaxDecodeLength(10).get()).get()) { + final IOException exception = assertThrows(IOException.class, stream::read); + assertTrue(exception.getCause() instanceof IllegalArgumentException); + assertEquals(88, source.available()); + } + } + + @Test + void testInvalidLimitRejected() { + assertThrows(IllegalArgumentException.class, () -> Base58.builder().setMaxDecodeLength(0)); + assertThrows(IllegalArgumentException.class, () -> Base58.builder().setMaxDecodeLength(-1)); + } + + @Test + void testNonzeroDigitsAtLimit() { + final Base58 codec = new Base58(); + final byte[] encoded = new byte[Base58.DEFAULT_MAX_DECODE_LENGTH]; + Arrays.fill(encoded, (byte) 'z'); + assertArrayEquals(encoded, codec.encode(codec.decode(encoded))); + final byte[] over = Arrays.copyOf(encoded, encoded.length + 1); + over[encoded.length] = 'z'; + assertThrows(IllegalArgumentException.class, () -> codec.decode(over)); + assertThrows(IllegalArgumentException.class, () -> codec.decode(StringUtils.newStringUsAscii(over))); + assertThrows(IllegalArgumentException.class, () -> codec.decode((Object) over)); + } + + @ParameterizedTest + @ValueSource(ints = { 1, 3, 10 }) + void testOutputStreamRejectsCrossingChunk(final int chunkSize) throws IOException { + final ByteArrayOutputStream sink = new ByteArrayOutputStream(); + try (Base58OutputStream stream = Base58OutputStream.builder().setOutputStream(sink).setEncode(false) + .setBaseNCodec(Base58.builder().setMaxDecodeLength(10).get()).get()) { + int written = 0; + while (written < 10) { + final int length = Math.min(chunkSize, 10 - written); + stream.write(ones(length)); + written += length; + } + final IOException exception = assertThrows(IOException.class, () -> stream.write('1')); + assertTrue(exception.getCause() instanceof IllegalArgumentException); + assertEquals(0, sink.size()); + } + assertArrayEquals(new byte[10], sink.toByteArray()); + } + + @Test + void testRejectsBeforeBuffering() { + final Base58 codec = Base58.builder().setMaxDecodeLength(10).get(); + final BaseNCodec.Context context = new BaseNCodec.Context(); + codec.decode(ones(8), 0, 8, context); + assertThrows(IllegalArgumentException.class, () -> codec.decode(ones(3), 0, 3, context)); + assertArrayEquals(ones(8), context.buffer); + // The cumulative check must not wrap around when adding the chunk length. + assertThrows(IllegalArgumentException.class, () -> codec.decode(ones(1), 0, Integer.MAX_VALUE, context)); + assertArrayEquals(ones(8), context.buffer); + } + + @Test + void testRoundTripUnaffected() { + final Base58 codec = new Base58(); + final byte[] data = { 0, 0, 1, 2, 3, 4, 5, -1, 127 }; + assertArrayEquals(data, codec.decode(codec.encode(data))); + } +} diff --git a/src/test/java/org/apache/commons/codec/binary/Base58Test.java b/src/test/java/org/apache/commons/codec/binary/Base58Test.java index 4ddc138f..15c6c170 100644 --- a/src/test/java/org/apache/commons/codec/binary/Base58Test.java +++ b/src/test/java/org/apache/commons/codec/binary/Base58Test.java @@ -132,7 +132,7 @@ public class Base58Test { @ValueSource(ints = { 20_000, 40_000, 80_000, 160_000, 320_000 }) void testDecodeLargeInput(final int n) { // any valid non-'1' Base58 char - new Base58().decode(ArrayFill.fill(new byte[n], (byte) 'z')); + Base58.builder().setMaxDecodeLength(n).get().decode(ArrayFill.fill(new byte[n], (byte) 'z')); } /** @@ -166,7 +166,7 @@ public class Base58Test { final byte[] data = new byte[random.nextInt(BOUND) + 1]; Arrays.fill(data, (byte) i); final byte[] enc = new Base58().encode(data); - final byte[] dec = new Base58().decode(enc); + final byte[] dec = Base58.builder().setMaxDecodeLength(BOUND * 2).get().decode(enc); assertArrayEqualsAt(data, dec, i); } } @@ -177,7 +177,7 @@ public class Base58Test { final byte[] data = new byte[random.nextInt(BOUND) + 1]; random.nextBytes(data); final byte[] enc = new Base58().encode(data); - final byte[] dec = new Base58().decode(enc); + final byte[] dec = Base58.builder().setMaxDecodeLength(BOUND * 2).get().decode(enc); assertArrayEqualsAt(data, dec, i); } }
