aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts
diff options
context:
space:
mode:
authorRemco Bloemen <Recmo@users.noreply.github.com>2018-06-19 19:53:25 +0800
committerGitHub <noreply@github.com>2018-06-19 19:53:25 +0800
commit66dc70c057d805f0abf84fe5dd13bf1aba82ab77 (patch)
tree227311583680382ccc911a8445430744a8b87cca /packages/contracts
parentf3ae5d8160f2e8a2fea8d045d9a02e37a7cdaa21 (diff)
parent82d1412d456ee28d80597208a241a2b62f561837 (diff)
downloaddexon-sol-tools-66dc70c057d805f0abf84fe5dd13bf1aba82ab77.tar.gz
dexon-sol-tools-66dc70c057d805f0abf84fe5dd13bf1aba82ab77.tar.zst
dexon-sol-tools-66dc70c057d805f0abf84fe5dd13bf1aba82ab77.zip
Merge pull request #683 from 0xProject/fix/contracts/memcpy
Simplified handling of source < 32 edge case
Diffstat (limited to 'packages/contracts')
-rw-r--r--packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol22
1 files changed, 12 insertions, 10 deletions
diff --git a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol
index 6afb9973a..97fb5fb0f 100644
--- a/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol
+++ b/packages/contracts/src/contracts/current/utils/LibMem/LibMem.sol
@@ -80,9 +80,6 @@ contract LibMem
//
if (source > dest) {
assembly {
- // Record the total number of full words to copy
- let nWords := div(length, 32)
-
// We subtract 32 from `sEnd` and `dEnd` because it
// is easier to compare with in the loop, and these
// are also the addresses we need for copying the
@@ -98,20 +95,19 @@ contract LibMem
let last := mload(sEnd)
// Copy whole words front to back
- for {let i := 0} lt(i, nWords) {i := add(i, 1)} {
+ // Note: the first check is always true,
+ // this could have been a do-while loop.
+ for {} lt(source, sEnd) {} {
mstore(dest, mload(source))
source := add(source, 32)
dest := add(dest, 32)
}
-
+
// Write the last 32 bytes
mstore(dEnd, last)
}
} else {
assembly {
- // Record the total number of full words to copy
- let nWords := div(length, 32)
-
// We subtract 32 from `sEnd` and `dEnd` because those
// are the starting points when copying a word at the end.
length := sub(length, 32)
@@ -125,12 +121,18 @@ contract LibMem
let first := mload(source)
// Copy whole words back to front
- for {let i := 0} lt(i, nWords) {i := add(i, 1)} {
+ // We use a signed comparisson here to allow dEnd to become
+ // negative (happens when source and dest < 32). Valid
+ // addresses in local memory will never be larger than
+ // 2**255, so they can be safely re-interpreted as signed.
+ // Note: the first check is always true,
+ // this could have been a do-while loop.
+ for {} slt(dest, dEnd) {} {
mstore(dEnd, mload(sEnd))
sEnd := sub(sEnd, 32)
dEnd := sub(dEnd, 32)
}
-
+
// Write the first 32 bytes
mstore(dest, first)
}