Skip to content

Commit 8cd4c44

Browse files
fix: using Data.startIndex to safely handle decoding of Data and Data slices
1 parent bfcf028 commit 8cd4c44

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

Sources/Web3Core/EthereumABI/ABIDecoding.swift

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,28 @@ extension ABIDecoder {
3434
guard let elementItself = elData, let nextElementPointer = nextPtr else {
3535
return (nil, nil)
3636
}
37+
let startIndex = UInt64(elementItself.startIndex)
3738
switch type {
3839
case .uint(let bits):
3940
guard elementItself.count >= 32 else {break}
4041
let mod = BigUInt(1) << bits
41-
let dataSlice = elementItself[0 ..< 32]
42+
let dataSlice = elementItself[startIndex ..< startIndex + 32]
4243
let v = BigUInt(dataSlice) % mod
4344
return (v, type.memoryUsage)
4445
case .int(let bits):
4546
guard elementItself.count >= 32 else {break}
4647
let mod = BigInt(1) << bits
47-
let dataSlice = elementItself[0 ..< 32]
48+
let dataSlice = elementItself[startIndex ..< startIndex + 32]
4849
let v = BigInt.fromTwosComplement(data: dataSlice) % mod
4950
return (v, type.memoryUsage)
5051
case .address:
5152
guard elementItself.count >= 32 else {break}
52-
let dataSlice = elementItself[12 ..< 32]
53+
let dataSlice = elementItself[startIndex + 12 ..< startIndex + 32]
5354
let address = EthereumAddress(dataSlice)
5455
return (address, type.memoryUsage)
5556
case .bool:
5657
guard elementItself.count >= 32 else {break}
57-
let dataSlice = elementItself[0 ..< 32]
58+
let dataSlice = elementItself[startIndex ..< startIndex + 32]
5859
let v = BigUInt(dataSlice)
5960
if v == BigUInt(36) ||
6061
v == BigUInt(32) ||
@@ -69,33 +70,33 @@ extension ABIDecoder {
6970
}
7071
case .bytes(let length):
7172
guard elementItself.count >= 32 else {break}
72-
let dataSlice = elementItself[0 ..< length]
73+
let dataSlice = elementItself[startIndex ..< startIndex + length]
7374
return (Data(dataSlice), type.memoryUsage)
7475
case .string:
7576
guard elementItself.count >= 32 else {break}
76-
var dataSlice = elementItself[0 ..< 32]
77+
var dataSlice = elementItself[startIndex ..< startIndex + 32]
7778
let length = UInt64(BigUInt(dataSlice))
78-
guard elementItself.count >= 32+length else {break}
79+
guard elementItself.count >= 32 + length else {break}
7980
dataSlice = elementItself[32 ..< 32 + length]
8081
guard let string = String(data: dataSlice, encoding: .utf8) else {break}
8182
return (string, type.memoryUsage)
8283
case .dynamicBytes:
8384
guard elementItself.count >= 32 else {break}
84-
var dataSlice = elementItself[0 ..< 32]
85+
var dataSlice = elementItself[startIndex ..< startIndex + 32]
8586
let length = UInt64(BigUInt(dataSlice))
86-
guard elementItself.count >= 32+length else {break}
87-
dataSlice = elementItself[32 ..< 32 + length]
87+
guard elementItself.count >= 32 + length else {break}
88+
dataSlice = elementItself[startIndex + 32 ..< startIndex + 32 + length]
8889
return (Data(dataSlice), nextElementPointer)
8990
case .array(type: let subType, length: let length):
9091
switch type.arraySize {
9192
case .dynamicSize:
9293
if subType.isStatic {
9394
// uint[] like, expect length and elements
9495
guard elementItself.count >= 32 else {break}
95-
var dataSlice = elementItself[0 ..< 32]
96+
var dataSlice = elementItself[startIndex ..< startIndex + 32]
9697
let length = UInt64(BigUInt(dataSlice))
9798
guard elementItself.count >= 32 + subType.memoryUsage*length else {break}
98-
dataSlice = elementItself[32 ..< 32 + subType.memoryUsage*length]
99+
dataSlice = elementItself[startIndex + 32 ..< startIndex + 32 + subType.memoryUsage*length]
99100
var subpointer: UInt64 = 32
100101
var toReturn = [Any]()
101102
for _ in 0 ..< length {
@@ -108,10 +109,10 @@ extension ABIDecoder {
108109
} else {
109110
// in principle is true for tuple[], so will work for string[] too
110111
guard elementItself.count >= 32 else {break}
111-
var dataSlice = elementItself[0 ..< 32]
112+
var dataSlice = elementItself[startIndex ..< startIndex + 32]
112113
let length = UInt64(BigUInt(dataSlice))
113114
guard elementItself.count >= 32 else {break}
114-
dataSlice = Data(elementItself[32 ..< elementItself.count])
115+
dataSlice = Data(elementItself[startIndex + 32 ..< UInt64(elementItself.count)])
115116
var subpointer: UInt64 = 0
116117
var toReturn = [Any]()
117118
for _ in 0 ..< length {
@@ -179,7 +180,7 @@ extension ABIDecoder {
179180
}
180181
case .function:
181182
guard elementItself.count >= 32 else {break}
182-
let dataSlice = elementItself[8 ..< 32]
183+
let dataSlice = elementItself[startIndex + 8 ..< startIndex + 32]
183184
return (dataSlice, type.memoryUsage)
184185
}
185186
return (nil, nil)
@@ -209,7 +210,8 @@ extension ABIDecoder {
209210
return (nil, nil)
210211
}
211212
let elementPointer = UInt64(bn)
212-
let elementItself = data[elementPointer ..< UInt64(data.count)]
213+
let startIndex = UInt64(data.startIndex)
214+
let elementItself = data[startIndex + elementPointer ..< startIndex + UInt64(data.count)]
213215
let nextElement = pointer + type.memoryUsage
214216
return (Data(elementItself), nextElement)
215217
}

0 commit comments

Comments
 (0)