Skip to content

Commit 95bbcf4

Browse files
authored
Ensure ABI decoder rejects ZST offsets (#359)
* Add ZST regression test * Move ZST regression test into decoder spec
1 parent 3cd1e9d commit 95bbcf4

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

lib/eth/abi/decoder.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,14 @@ def type(type, arg)
4343
# Case: decoding array of string/bytes
4444
else
4545
l = Util.deserialize_big_endian_to_int arg[0, 32]
46+
raise DecodingError, "Wrong data size for dynamic array" unless arg.size >= 32 + 32 * l
4647

4748
# Decode each element of the array
4849
(1..l).map do |i|
4950
pointer = Util.deserialize_big_endian_to_int arg[i * 32, 32] # Pointer to the size of the array's element
51+
raise DecodingError, "Offset out of bounds" if pointer < 32 * l || pointer > arg.size - 64
5052
data_l = Util.deserialize_big_endian_to_int arg[32 + pointer, 32] # length of the element
53+
raise DecodingError, "Offset out of bounds" if pointer + 32 + Util.ceil32(data_l) > arg.size
5154
type(Type.parse(type.base_type), arg[pointer + 32, Util.ceil32(data_l) + 32])
5255
end
5356
end
@@ -74,9 +77,15 @@ def type(type, arg)
7477
nested_sub = type.nested_sub
7578

7679
if nested_sub.dynamic?
77-
offsets = (0...l).map { |i| Util.deserialize_big_endian_to_int arg[32 + 32 * i, 32] }
80+
raise DecodingError, "Wrong data size for dynamic array" unless arg.size >= 32 + 32 * l
81+
offsets = (0...l).map do |i|
82+
off = Util.deserialize_big_endian_to_int arg[32 + 32 * i, 32]
83+
raise DecodingError, "Offset out of bounds" if off < 32 * l || off > arg.size - 64
84+
off
85+
end
7886
offsets.map { |off| type(nested_sub, arg[32 + off..]) }
7987
else
88+
raise DecodingError, "Wrong data size for dynamic array" unless arg.size >= 32 + nested_sub.size * l
8089
# decoded dynamic-sized arrays with static sub-types
8190
(0...l).map { |i| type(nested_sub, arg[32 + nested_sub.size * i, nested_sub.size]) }
8291
end

spec/eth/abi/decoder_spec.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,15 @@
8383
# uncovered edge-cases
8484
expect { Abi::Decoder.primitive_type(Abi::Type.new("foo", 32, []), "bar") }.to raise_error Abi::DecodingError
8585
end
86+
87+
describe "ZST robustness" do
88+
it "rejects self-referential dynamic array offsets" do
89+
payload = "0000000000000000000000000000000000000000000000000000000000000020" \
90+
"0000000000000000000000000000000000000000000000000000000000000002" \
91+
"0000000000000000000000000000000000000000000000000000000000000020" \
92+
"0000000000000000000000000000000000000000000000000000000000000020"
93+
data = Util.hex_to_bin(payload)
94+
expect { Abi.decode(["uint256[][]"], data) }.to raise_error Abi::DecodingError
95+
end
96+
end
8697
end

0 commit comments

Comments
 (0)