From 7f34d99f2b716752f62baf2d9283089433e3a331 Mon Sep 17 00:00:00 2001 From: Qi Zhou Date: Tue, 8 Feb 2022 01:35:50 -0800 Subject: [PATCH] Fix out of memory bound issue of Memory.copy() The original implementation assumes the memory size >= max(src, dest) + ROUND_UP(len, 32), which is not always true (and result in unexpected revert). The new implement will use reverse copy so that no out-of-copy memory will be touched (and also simplified the mask so that out-of-copy memory is unchanged). --- src/unsafe/Memory.sol | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/unsafe/Memory.sol b/src/unsafe/Memory.sol index 71b9993..417f350 100644 --- a/src/unsafe/Memory.sol +++ b/src/unsafe/Memory.sol @@ -56,20 +56,27 @@ library Memory { // the bytes. function copy(uint src, uint dest, uint len) internal pure { // Copy word-length chunks while possible + // Reverse copy to prevent out of memory bound error + src = src + len; + dest = dest + len; for (; len >= WORD_SIZE; len -= WORD_SIZE) { + dest -= WORD_SIZE; + src -= WORD_SIZE; + assembly { mstore(dest, mload(src)) } - dest += WORD_SIZE; - src += WORD_SIZE; + } + + if (len == 0) { + return; } // Copy remaining bytes - uint mask = 256 ** (WORD_SIZE - len) - 1; + src = src - len; + dest = dest - len; assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) + mstore(dest, mload(src)) } }