Skip to content

Commit c97c3ad

Browse files
committed
Fix base58 en/decoding of arrays of zero bytes.
1 parent 4b88416 commit c97c3ad

File tree

4 files changed

+24
-8
lines changed

4 files changed

+24
-8
lines changed

src/main/java/io/ipfs/multibase/BaseN.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ public class BaseN {
77
static String encode(final String alphabet, final BigInteger base, final byte[] input) {
88
// TODO: This could be a lot more efficient.
99
BigInteger bi = new BigInteger(1, input);
10+
boolean isZero = bi.equals(BigInteger.ZERO);
1011
StringBuffer s = new StringBuffer();
1112
while (bi.compareTo(base) >= 0) {
1213
BigInteger mod = bi.mod(base);
1314
s.insert(0, alphabet.charAt(mod.intValue()));
1415
bi = bi.subtract(mod).divide(base);
1516
}
16-
s.insert(0, alphabet.charAt(bi.intValue()));
17+
if (! isZero)
18+
s.insert(0, alphabet.charAt(bi.intValue()));
1719
// Convert leading zeros too.
1820
for (byte anInput : input) {
1921
if (anInput == 0)
@@ -33,9 +35,11 @@ static byte[] decode(final String alphabet, final BigInteger base, final String
3335
boolean stripSignByte = bytes.length > 1 && bytes[0] == 0 && bytes[1] < 0;
3436
// Count the leading zeros, if any.
3537
int leadingZeros = 0;
36-
for (int i = 0; input.charAt(i) == alphabet.charAt(0); i++) {
38+
for (int i = 0; i < input.length() && input.charAt(i) == alphabet.charAt(0); i++) {
3739
leadingZeros++;
3840
}
41+
if (leadingZeros == input.length())
42+
return new byte[leadingZeros];
3943
// Now cut/pad correctly. Java 6 has a convenience for this, but Android can't use it.
4044
byte[] tmp = new byte[bytes.length - (stripSignByte ? 1 : 0) + leadingZeros];
4145
System.arraycopy(bytes, stripSignByte ? 1 : 0, tmp, leadingZeros, tmp.length - leadingZeros);

src/main/main.iml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<module type="JAVA_MODULE" version="4">
3-
<component name="NewModuleRootManager" inherit-compiler-output="true">
3+
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
44
<exclude-output />
55
<content url="file://$MODULE_DIR$">
66
<sourceFolder url="file://$MODULE_DIR$/java" isTestSource="false" />
77
</content>
8-
<orderEntry type="inheritedJdk" />
8+
<orderEntry type="jdk" jdkName="1.8 Oracle" jdkType="JavaSDK" />
99
<orderEntry type="sourceFolder" forTests="false" />
1010
</component>
1111
</module>

src/test/java/io/ipfs/multibase/MultibaseTest.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,27 @@ public class MultibaseTest {
1212

1313
@Test
1414
public void base58Test() {
15-
List<String> examples = Arrays.asList("zQmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB",
16-
"zQmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy");
15+
List<String> examples = Arrays.asList(
16+
"zQmPZ9gcCEpqKTo6aq61g2nXGUhM4iCL3ewB6LDXZCtioEB",
17+
"zQmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy",
18+
"z11");
1719
for (String example: examples) {
1820
byte[] output = Multibase.decode(example);
1921
String encoded = Multibase.encode(Multibase.Base.Base58BTC, output);
2022
assertEquals(example, encoded);
2123
}
2224
}
2325

26+
@Test
27+
public void zeroBytesBase58() {
28+
for (int i=0; i < 32; i++) {
29+
String encoded = Multibase.encode(Multibase.Base.Base58BTC, new byte[i]);
30+
byte[] output = Multibase.decode(encoded);
31+
if (! Arrays.equals(output, new byte[i]))
32+
throw new IllegalStateException("Failed to round trip zero array of length " + i);
33+
}
34+
}
35+
2436
@Test
2537
public void base16Test() {
2638
List<String> examples = Arrays.asList("f234abed8debede",

src/test/test.iml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<module type="JAVA_MODULE" version="4">
3-
<component name="NewModuleRootManager" inherit-compiler-output="true">
3+
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
44
<exclude-output />
55
<content url="file://$MODULE_DIR$">
66
<sourceFolder url="file://$MODULE_DIR$/java" isTestSource="true" />
77
</content>
8-
<orderEntry type="inheritedJdk" />
8+
<orderEntry type="jdk" jdkName="1.8 Oracle" jdkType="JavaSDK" />
99
<orderEntry type="sourceFolder" forTests="false" />
1010
<orderEntry type="library" name="lib" level="project" />
1111
<orderEntry type="module" module-name="main" />

0 commit comments

Comments
 (0)