Skip to content

Commit

Permalink
Add some input vaklidation to RLP decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
benjaminion committed Aug 12, 2020
1 parent 57eb150 commit ac3991d
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 2 deletions.
17 changes: 15 additions & 2 deletions rlp/src/main/java/org/web3j/rlp/RlpDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ private static void traverse(byte[] data, int startPos, int endPos, RlpList rlpL

byte strLen = (byte) (prefix - OFFSET_SHORT_STRING);

// Input validation
if (strLen > data.length - (startPos + 1)) {
throw new RuntimeException("RLP length mismatch");
}

byte[] rlpData = new byte[strLen];
System.arraycopy(data, startPos + 1, rlpData, 0, strLen);

Expand All @@ -119,6 +124,11 @@ private static void traverse(byte[] data, int startPos, int endPos, RlpList rlpL
byte lenOfStrLen = (byte) (prefix - OFFSET_LONG_STRING);
int strLen = calcLength(lenOfStrLen, data, startPos);

// Input validation
if (strLen > data.length - (startPos + lenOfStrLen + 1)) {
throw new RuntimeException("RLP length mismatch");
}

// now we can parse an item for data[1]..data[length]
byte[] rlpData = new byte[strLen];
System.arraycopy(data, startPos + lenOfStrLen + 1, rlpData, 0, strLen);
Expand Down Expand Up @@ -171,11 +181,14 @@ private static void traverse(byte[] data, int startPos, int endPos, RlpList rlpL

private static int calcLength(int lengthOfLength, byte[] data, int pos) {
byte pow = (byte) (lengthOfLength - 1);
int length = 0;
long length = 0;
for (int i = 1; i <= lengthOfLength; ++i) {
length += (data[pos + i] & 0xff) << (8 * pow);
pow--;
}
return length;
if (length < 0 || length > Integer.MAX_VALUE) {
throw new RuntimeException("RLP too many bytes to decode");
}
return (int) length;
}
}
11 changes: 11 additions & 0 deletions rlp/src/test/java/org/web3j/rlp/RlpDecoderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.web3j.utils.Numeric;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class RlpDecoderTest {
Expand Down Expand Up @@ -321,5 +322,15 @@ public void testRLPDecode() {
.getValues()
.size(),
(9));

// Regression test: this would previously throw OutOfMemoryError as it tried to allocate 2GB
// for the non-existent data
assertThrows(
RuntimeException.class,
(() ->
RlpDecoder.decode(
new byte[] {
(byte) 0xbb, (byte) 0x7f, (byte) 0xff, (byte) 0xff, (byte) 0xff
})));
}
}

0 comments on commit ac3991d

Please sign in to comment.