@@ -61,10 +61,13 @@ library ERC7579Utils {
61
61
/// @dev The module type is not supported.
62
62
error ERC7579UnsupportedModuleType (uint256 moduleTypeId );
63
63
64
+ /// @dev Input calldata not properly formatted and possibly malicious.
65
+ error ERC7579DecodingError ();
66
+
64
67
/// @dev Executes a single call.
65
68
function execSingle (
66
- ExecType execType ,
67
- bytes calldata executionCalldata
69
+ bytes calldata executionCalldata ,
70
+ ExecType execType
68
71
) internal returns (bytes [] memory returnData ) {
69
72
(address target , uint256 value , bytes calldata callData ) = decodeSingle (executionCalldata);
70
73
returnData = new bytes [](1 );
@@ -73,8 +76,8 @@ library ERC7579Utils {
73
76
74
77
/// @dev Executes a batch of calls.
75
78
function execBatch (
76
- ExecType execType ,
77
- bytes calldata executionCalldata
79
+ bytes calldata executionCalldata ,
80
+ ExecType execType
78
81
) internal returns (bytes [] memory returnData ) {
79
82
Execution[] calldata executionBatch = decodeBatch (executionCalldata);
80
83
returnData = new bytes [](executionBatch.length );
@@ -91,8 +94,8 @@ library ERC7579Utils {
91
94
92
95
/// @dev Executes a delegate call.
93
96
function execDelegateCall (
94
- ExecType execType ,
95
- bytes calldata executionCalldata
97
+ bytes calldata executionCalldata ,
98
+ ExecType execType
96
99
) internal returns (bytes [] memory returnData ) {
97
100
(address target , bytes calldata callData ) = decodeDelegate (executionCalldata);
98
101
returnData = new bytes [](1 );
@@ -169,12 +172,40 @@ library ERC7579Utils {
169
172
}
170
173
171
174
/// @dev Decodes a batch of executions. See {encodeBatch}.
175
+ ///
176
+ /// NOTE: This function runs some checks and will throw a {ERC7579DecodingError} if the input is not properly formatted.
172
177
function decodeBatch (bytes calldata executionCalldata ) internal pure returns (Execution[] calldata executionBatch ) {
173
- assembly ("memory-safe" ) {
174
- let ptr := add (executionCalldata.offset, calldataload (executionCalldata.offset))
175
- // Extract the ERC7579 Executions
176
- executionBatch.offset := add (ptr, 32 )
177
- executionBatch.length := calldataload (ptr)
178
+ unchecked {
179
+ uint256 bufferLength = executionCalldata.length ;
180
+
181
+ // Check executionCalldata is not empty.
182
+ if (bufferLength < 32 ) revert ERC7579DecodingError ();
183
+
184
+ // Get the offset of the array (pointer to the array length).
185
+ uint256 arrayLengthPointer = uint256 (bytes32 (executionCalldata[0 :32 ]));
186
+
187
+ // The array length (at arrayLengthPointer) should be 32 bytes long. We check that this is within the
188
+ // buffer bounds. Since we know bufferLength is at least 32, we can subtract with no overflow risk.
189
+ if (arrayLengthPointer > bufferLength - 32 ) revert ERC7579DecodingError ();
190
+
191
+ // Get the array length. arrayLengthPointer + 32 is bounded by bufferLength so it does not overflow.
192
+ uint256 arrayLength = uint256 (bytes32 (executionCalldata[arrayLengthPointer:arrayLengthPointer + 32 ]));
193
+
194
+ // Check that the buffer is long enough to store the array elements as "offset pointer":
195
+ // - each element of the array is an "offset pointer" to the data.
196
+ // - each "offset pointer" (to an array element) takes 32 bytes.
197
+ // - validity of the calldata at that location is checked when the array element is accessed, so we only
198
+ // need to check that the buffer is large enough to hold the pointers.
199
+ //
200
+ // Since we know bufferLength is at least arrayLengthPointer + 32, we can subtract with no overflow risk.
201
+ // Solidity limits length of such arrays to 2**64-1, this guarantees `arrayLength * 32` does not overflow.
202
+ if (arrayLength > type (uint64 ).max || bufferLength - arrayLengthPointer - 32 < arrayLength * 32 )
203
+ revert ERC7579DecodingError ();
204
+
205
+ assembly ("memory-safe" ) {
206
+ executionBatch.offset := add (add (executionCalldata.offset, arrayLengthPointer), 32 )
207
+ executionBatch.length := arrayLength
208
+ }
178
209
}
179
210
}
180
211
0 commit comments