Skip to content

Commit 15be984

Browse files
authored
🐞 Fix p extend memory bug (#1372)
1 parent 2abaa64 commit 15be984

5 files changed

Lines changed: 68 additions & 5 deletions

File tree

src/utils/DynamicArrayLib.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ library DynamicArrayLib {
567567
// Approximately more than double the capacity to ensure more than enough space.
568568
let newCap := add(cap, or(cap, newArrBytesLen))
569569
// If the memory is contiguous, we can simply expand it.
570-
if iszero(or(xor(mload(0x40), add(arrData, add(0x20, cap))), eq(arrData, 0x60))) {
570+
if iszero(or(xor(mload(0x40), add(arrData, add(0x20, cap))), iszero(cap))) {
571571
mstore(sub(arrData, 0x20), mul(prime, newCap)) // Store the capacity.
572572
mstore(0x40, add(arrData, add(0x20, newCap))) // Expand the memory allocation.
573573
break

src/utils/DynamicBufferLib.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ library DynamicBufferLib {
101101
// Approximately more than double the capacity to ensure more than enough space.
102102
let newCap := and(add(cap, add(or(cap, newBufDataLen), 0x20)), w)
103103
// If the memory is contiguous, we can simply expand it.
104-
if iszero(or(xor(mload(0x40), add(bufData, add(0x40, cap))), eq(bufData, 0x60))) {
104+
if iszero(or(xor(mload(0x40), add(bufData, add(0x40, cap))), iszero(cap))) {
105105
// Store `cap * prime` in the word before the length.
106106
mstore(add(bufData, w), mul(prime, newCap))
107107
mstore(0x40, add(bufData, add(0x40, newCap))) // Expand the memory allocation.

src/utils/g/DynamicArrayLib.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ library DynamicArrayLib {
571571
// Approximately more than double the capacity to ensure more than enough space.
572572
let newCap := add(cap, or(cap, newArrBytesLen))
573573
// If the memory is contiguous, we can simply expand it.
574-
if iszero(or(xor(mload(0x40), add(arrData, add(0x20, cap))), eq(arrData, 0x60))) {
574+
if iszero(or(xor(mload(0x40), add(arrData, add(0x20, cap))), iszero(cap))) {
575575
mstore(sub(arrData, 0x20), mul(prime, newCap)) // Store the capacity.
576576
mstore(0x40, add(arrData, add(0x20, newCap))) // Expand the memory allocation.
577577
break

src/utils/g/DynamicBufferLib.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ library DynamicBufferLib {
105105
// Approximately more than double the capacity to ensure more than enough space.
106106
let newCap := and(add(cap, add(or(cap, newBufDataLen), 0x20)), w)
107107
// If the memory is contiguous, we can simply expand it.
108-
if iszero(or(xor(mload(0x40), add(bufData, add(0x40, cap))), eq(bufData, 0x60))) {
108+
if iszero(or(xor(mload(0x40), add(bufData, add(0x40, cap))), iszero(cap))) {
109109
// Store `cap * prime` in the word before the length.
110110
mstore(add(bufData, w), mul(prime, newCap))
111111
mstore(0x40, add(bufData, add(0x40, newCap))) // Expand the memory allocation.

test/DynamicArrayLib.t.sol

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,10 +239,73 @@ contract DynamicArrayLibTest is SoladyTest {
239239
}
240240
}
241241

242-
function testDynamicArrayCopy(uint256[] memory data) public {
242+
function testDynamicArrayCopyOrAllSlice() public {
243+
uint256[] memory data;
244+
uint256[] memory data2 = new uint256[](1);
245+
data2[0] = 600972374956821603611096798192277940001591154517179782006087886208744463727;
246+
this.testDynamicArrayCopyOrAllSlice(data, data2, 0);
247+
}
248+
249+
function testDynamicArrayCopyOrAllSlice(
250+
uint256[] calldata data,
251+
uint256[] calldata data2,
252+
uint256 r
253+
) public {
254+
DynamicArrayLib.DynamicArray memory a;
255+
DynamicArrayLib.DynamicArray memory b;
256+
DynamicArrayLib.DynamicArray memory aCopy;
257+
for (uint256 i; i < data.length; ++i) {
258+
a.p(data[i] & (2 ** 160 - 1));
259+
b.p(data[i]);
260+
if (r & 2 == 0) {
261+
_checkMemory(a.data);
262+
_checkMemory(b.data);
263+
}
264+
}
265+
bytes32 h = keccak256(abi.encodePacked(b.data));
266+
aCopy = r & 1 == 0 ? a.copy() : a.slice(0);
267+
/// @solidity memory-safe-assembly
268+
assembly {
269+
log0(a, 0x20)
270+
log0(b, 0x20)
271+
log0(aCopy, 0x20)
272+
}
273+
for (uint256 i; i < data2.length; ++i) {
274+
aCopy.p(data2[i]);
275+
}
276+
/// @solidity memory-safe-assembly
277+
assembly {
278+
log0(a, 0x20)
279+
log0(b, 0x20)
280+
log0(aCopy, 0x20)
281+
}
282+
for (uint256 i; i < data2.length; ++i) {
283+
a.p(data2[i]);
284+
}
285+
/// @solidity memory-safe-assembly
286+
assembly {
287+
log0(a, 0x20)
288+
log0(b, 0x20)
289+
log0(aCopy, 0x20)
290+
}
291+
assertEq(a.data, aCopy.data);
292+
assertEq(keccak256(abi.encodePacked(b.data)), h);
293+
}
294+
295+
function testDynamicArrayCopy(uint256[] memory data, uint256 r) public {
296+
if (r & 0xff00 == 0) {
297+
/// @solidity memory-safe-assembly
298+
assembly {
299+
data := 0x60
300+
}
301+
}
243302
DynamicArrayLib.DynamicArray memory a;
244303
a.data = data;
245304
DynamicArrayLib.DynamicArray memory b = a.copy();
305+
if (r & 2 == 0) {
306+
_checkMemory(a.data);
307+
_checkMemory(b.data);
308+
}
246309
assertEq(a.data, b.data);
247310
a.p(1);
248311
assertNotEq(a.data, b.data);

0 commit comments

Comments
 (0)