Skip to content

Commit 32a2fda

Browse files
author
Chris Chinchilla
committed
Reference code for RLP decoding rejects some invalid encodings
1 parent 6cb0ea5 commit 32a2fda

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

RLP.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,32 @@ def decode_length(input):
128128
return (0, 1, str)
129129
elif prefix <= 0xb7 and length > prefix - 0x80:
130130
strLen = prefix - 0x80
131+
# ADDED:
132+
if strLen == 1 and ord(input[1]) <= 0x7f:
133+
raise Exception("single byte below 128 must be encoded as itself")
131134
return (1, strLen, str)
132135
elif prefix <= 0xbf and length > prefix - 0xb7 and length > prefix - 0xb7 + to_integer(substr(input, 1, prefix - 0xb7)):
133136
lenOfStrLen = prefix - 0xb7
137+
# ADDED:
138+
if input[1] == 0:
139+
raise Exception("multi-byte length must have no leading zero");
134140
strLen = to_integer(substr(input, 1, lenOfStrLen))
141+
# ADDED:
142+
if strLen < 56:
143+
raise Exception("length below 56 must be encoded in one byte");
135144
return (1 + lenOfStrLen, strLen, str)
136145
elif prefix <= 0xf7 and length > prefix - 0xc0:
137146
listLen = prefix - 0xc0;
138147
return (1, listLen, list)
139148
elif prefix <= 0xff and length > prefix - 0xf7 and length > prefix - 0xf7 + to_integer(substr(input, 1, prefix - 0xf7)):
140149
lenOfListLen = prefix - 0xf7
150+
# ADDED:
151+
if input[1] == 0:
152+
raise Exception("multi-byte length must have no leading zero");
141153
listLen = to_integer(substr(input, 1, lenOfListLen))
154+
# ADDED:
155+
if listLen < 56:
156+
raise Exception("length below 56 must be encoded in one byte");
142157
return (1 + lenOfListLen, listLen, list)
143158
else:
144159
raise Exception("input don't conform RLP encoding form")
@@ -153,6 +168,8 @@ def to_integer(b):
153168
return ord(substr(b, -1)) + to_integer(substr(b, 0, -1)) * 256
154169
```
155170

171+
Note that the `decode_length` function rejects invalid encodings that have "non-optimal" lengths, namely (1) singleton strings whose only byte is below 128 that are encoded with a short (i.e. one-byte) length of 1 instead of as the strings themselves and (2) strings and lists with long (i.e. multi-byte) lengths with leading zeros (which must be absent) or below 56 (which should be encoded using short lengths).
172+
156173
### Implementations
157174
* Go: [go-ethereum](https://github.com/ethereum/go-ethereum/tree/master/rlp)
158175
* Java: [web3j](https://github.com/web3j/web3j/blob/master/rlp/src/main/java/org/web3j/rlp/RlpDecoder.java), [ethereumj](https://github.com/ethereumj/ethereumj/blob/master/ethereumj-core/src/main/java/org/ethereum/util/RLP.java), [headlong](https://github.com/esaulpaugh/headlong/tree/master/src/main/java/com/esaulpaugh/headlong/rlp)

0 commit comments

Comments
 (0)