Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(EVM): Fix data copy corner cases #1053

Merged
merged 3 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions system-contracts/SystemContractsHashes.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,49 @@
"contractName": "AccountCodeStorage",
"bytecodePath": "artifacts-zk/contracts-preprocessed/AccountCodeStorage.sol/AccountCodeStorage.json",
"sourceCodePath": "contracts-preprocessed/AccountCodeStorage.sol",
"bytecodeHash": "0x0100007757f0a993c2b61e4b7b980eac7c16f9461d56b872befad11edf1791ef",
"bytecodeHash": "0x01000077e38f3e974a8def22f43e6c3c566d7c18ba04a55dfbad90dfd972920b",
"sourceCodeHash": "0xfdac12f45b5cfd4abd12923206f2d6f253d11a6624783e079b55e975d573ceb6"
},
{
"contractName": "BootloaderUtilities",
"bytecodePath": "artifacts-zk/contracts-preprocessed/BootloaderUtilities.sol/BootloaderUtilities.json",
"sourceCodePath": "contracts-preprocessed/BootloaderUtilities.sol",
"bytecodeHash": "0x010006f1164848f2e7669df28198a273458ba1fdf1ed0a04321289821d624ad4",
"bytecodeHash": "0x010006f1264905c7690fec8739ef464fb0efe1b6a2b3d1ef9c8bc31021c2d3eb",
"sourceCodeHash": "0xed45097b2eaa4e47cd83f6feb3671d44adb49bac64c267844e76b3444605be19"
},
{
"contractName": "ComplexUpgrader",
"bytecodePath": "artifacts-zk/contracts-preprocessed/ComplexUpgrader.sol/ComplexUpgrader.json",
"sourceCodePath": "contracts-preprocessed/ComplexUpgrader.sol",
"bytecodeHash": "0x0100004772c49529c6ccb5f6b3b1ea23d7498a172b59f3aa8797443ab7ec423a",
"bytecodeHash": "0x0100004781f95009a16d912d2bf05573968ed0897b590791129e5c8cd6a66257",
"sourceCodeHash": "0x796046a914fb676ba2bbd337b2924311ee2177ce54571c18a2c3945755c83614"
},
{
"contractName": "Compressor",
"bytecodePath": "artifacts-zk/contracts-preprocessed/Compressor.sol/Compressor.json",
"sourceCodePath": "contracts-preprocessed/Compressor.sol",
"bytecodeHash": "0x0100013f346ef598ecf8a5ba86e2fa4b306816a89a5a96af611047f3508faf03",
"bytecodeHash": "0x0100013f94deb4d671b1f75987670fe3f875e0730aee2e4ae44d75f147201e38",
"sourceCodeHash": "0xc6f7cd8b21aae52ed3dd5083c09b438a7af142a4ecda6067c586770e8be745a5"
},
{
"contractName": "ContractDeployer",
"bytecodePath": "artifacts-zk/contracts-preprocessed/ContractDeployer.sol/ContractDeployer.json",
"sourceCodePath": "contracts-preprocessed/ContractDeployer.sol",
"bytecodeHash": "0x01000671f7ed086cc23329dd16d7e240c19b1a96c6571728c762f705f7c5549b",
"sourceCodeHash": "0x86897736464a0363c5b13c1d5796bfc6ba37e6eaadb848ed13ab69e54b16f21a"
"bytecodeHash": "0x0100067112f5b7b010c31dc21efe07f983df32f1908a48bd7084e8c967f19470",
"sourceCodeHash": "0x3a03e66288c63fb72abe909ae829fa9495dce051753687d4395d41971847826b"
},
{
"contractName": "Create2Factory",
"bytecodePath": "artifacts-zk/contracts-preprocessed/Create2Factory.sol/Create2Factory.json",
"sourceCodePath": "contracts-preprocessed/Create2Factory.sol",
"bytecodeHash": "0x0100003fc7635b13ed69e2a8e85908317afa68eee660998372981c7ca9991aaa",
"bytecodeHash": "0x0100003f93af5076860d7d80073c61d1f81a2b41b685d139f17320e337dc204c",
"sourceCodeHash": "0x114d9322a9ca654989f3e0b3b21f1311dbc4db84f443d054cd414f6414d84de3"
},
{
"contractName": "DefaultAccount",
"bytecodePath": "artifacts-zk/contracts-preprocessed/DefaultAccount.sol/DefaultAccount.json",
"sourceCodePath": "contracts-preprocessed/DefaultAccount.sol",
"bytecodeHash": "0x010005096489d3a6c7c9d18750a4bda0f78c7a7f71ec540cb9b0fb8f2970922b",
"bytecodeHash": "0x0100050989d91484a0d994fab1527c01f1f5fa39c9993945ae943874c4667e7d",
"sourceCodeHash": "0xef448fac6b6f1c217b6495ee134a3553e02dfb920fd46bc71de33672e64d9ab8"
},
{
Expand All @@ -59,56 +59,56 @@
"contractName": "ImmutableSimulator",
"bytecodePath": "artifacts-zk/contracts-preprocessed/ImmutableSimulator.sol/ImmutableSimulator.json",
"sourceCodePath": "contracts-preprocessed/ImmutableSimulator.sol",
"bytecodeHash": "0x010000333575bcc1f34a79d1b43bb8f69813d35463b602e8e1fb88d85806aee1",
"bytecodeHash": "0x01000033de8aeec22172e554f130cf986fc38c7c2d1fa0021d2197db9043b125",
"sourceCodeHash": "0x9659e69f7db09e8f60a8bb95314b1ed26afcc689851665cf27f5408122f60c98"
},
{
"contractName": "KnownCodesStorage",
"bytecodePath": "artifacts-zk/contracts-preprocessed/KnownCodesStorage.sol/KnownCodesStorage.json",
"sourceCodePath": "contracts-preprocessed/KnownCodesStorage.sol",
"bytecodeHash": "0x010000cdc5734c8109be1afdc5ad40c84157d9f19bc1967d8a128444bcce0360",
"bytecodeHash": "0x010000cdf509accfddca2517ef4a7ef699d898262af5e79f0e7c5c7966f12c6a",
"sourceCodeHash": "0x851fb5e170dfde39f1f9bc74654ec0b8f8f1d4c2fb20c06c77844c1e3ee0659a"
},
{
"contractName": "L1Messenger",
"bytecodePath": "artifacts-zk/contracts-preprocessed/L1Messenger.sol/L1Messenger.json",
"sourceCodePath": "contracts-preprocessed/L1Messenger.sol",
"bytecodeHash": "0x01000265966dd95109bdd779e6deeb4f531d0cd983fb053ed77fbb982f94607b",
"bytecodeHash": "0x010002659014fddc66937d91a9a4b149568ad0c7f6c3797ae7d5bd2a8ddd7877",
"sourceCodeHash": "0xa8768fdaac6d8804782f14e2a51bbe2b6be31dee9103b6d02d149ea8dc46eb6a"
},
{
"contractName": "L2BaseToken",
"bytecodePath": "artifacts-zk/contracts-preprocessed/L2BaseToken.sol/L2BaseToken.json",
"sourceCodePath": "contracts-preprocessed/L2BaseToken.sol",
"bytecodeHash": "0x010000f33e4c891018536ca207056f7536854b030d847fdd7f21eb5576b30ed4",
"bytecodeHash": "0x010000f3e13f08f85a3271fb8bc1bf70364933b63e9d7025f722d98bc589e9d0",
"sourceCodeHash": "0x8bdd2b4d0b53dba84c9f0af250bbaa2aad10b3de6747bba957f0bd3721090dfa"
},
{
"contractName": "MsgValueSimulator",
"bytecodePath": "artifacts-zk/contracts-preprocessed/MsgValueSimulator.sol/MsgValueSimulator.json",
"sourceCodePath": "contracts-preprocessed/MsgValueSimulator.sol",
"bytecodeHash": "0x01000059700408fe641af24437be3a197adfa4798b943594dc83f10a70bae855",
"bytecodeHash": "0x0100005978b4f9317489d511739a80bedb832092c8741a45ed636de64167aca0",
"sourceCodeHash": "0x082f3dcbc2fe4d93706c86aae85faa683387097d1b676e7ebd00f71ee0f13b71"
},
{
"contractName": "NonceHolder",
"bytecodePath": "artifacts-zk/contracts-preprocessed/NonceHolder.sol/NonceHolder.json",
"sourceCodePath": "contracts-preprocessed/NonceHolder.sol",
"bytecodeHash": "0x010000cffce37e7325318c746f5af8bd8d5f22236eabe2c5c78fc2acca5b418d",
"bytecodeHash": "0x010000cfa3b3ba69935156cb43bc4501fef0897c657dd0e5574064cad3243df0",
"sourceCodeHash": "0xcd0c0366effebf2c98c58cf96322cc242a2d1c675620ef5514b7ed1f0a869edc"
},
{
"contractName": "PubdataChunkPublisher",
"bytecodePath": "artifacts-zk/contracts-preprocessed/PubdataChunkPublisher.sol/PubdataChunkPublisher.json",
"sourceCodePath": "contracts-preprocessed/PubdataChunkPublisher.sol",
"bytecodeHash": "0x01000041a25a3ab6180cb1d752e742d9e39c8637b6c9e1e64a52d002f761b32d",
"bytecodeHash": "0x01000041332bbd6c2abad4bc30bb3d9a9a26d914c11e4bcc803cd0905eaff964",
"sourceCodeHash": "0xd7161e2c8092cf57b43c6220bc605c0e7e540bddcde1af24e2d90f75633b098e"
},
{
"contractName": "SystemContext",
"bytecodePath": "artifacts-zk/contracts-preprocessed/SystemContext.sol/SystemContext.json",
"sourceCodePath": "contracts-preprocessed/SystemContext.sol",
"bytecodeHash": "0x010001c56a15564c7f07cc0dc68099436b1b40110f2d011b957860e324f948d7",
"bytecodeHash": "0x010001c5415782e13f8c4026d2b1e3270b4c5ef92fb9fe731ff2a3c1ada12601",
"sourceCodeHash": "0xe2f6eb015d260aafe9405b28ef3ec27921add4de7f329b7ef61e0aa6c9365e29"
},
{
Expand All @@ -122,15 +122,15 @@
"contractName": "EvmEmulator",
"bytecodePath": "contracts-preprocessed/artifacts/EvmEmulator.yul/EvmEmulator.yul.zbin",
"sourceCodePath": "contracts-preprocessed/EvmEmulator.yul",
"bytecodeHash": "0x01000cb54199e828134a56d7302a7ed55ba8f0b54d898aa0f3949ca2774b1643",
"sourceCodeHash": "0xa1ce6b22af5b1be710181ea59b4a76879ccb0d4989d533c92965df1bbaa340b2"
"bytecodeHash": "0x01000cb5ab96098493fa599effb19ce9c6d8db6e9bfe34004ce3ff35e2225a75",
"sourceCodeHash": "0x86296ecb81fc9edf5aac32613dfd645b538535e264e02a12ec7cdc751018de5d"
},
{
"contractName": "EvmGasManager",
"bytecodePath": "contracts-preprocessed/artifacts/EvmGasManager.yul/EvmGasManager.yul.zbin",
"sourceCodePath": "contracts-preprocessed/EvmGasManager.yul",
"bytecodeHash": "0x010000697e213955edae21195912d2900639a2eba6d15f592a12bfb05b350966",
"sourceCodeHash": "0x1eb4cffcd8b9365bed383e199ab169af21a8ba809a685c0a36f89a128d8582f8"
"bytecodeHash": "0x01000073f07635332a31f5a0f84ae277e3462b0240ced32b9def9785c67e6a99",
"sourceCodeHash": "0x825dc1d9bec5128457a8b96eaf7ebf7c89dbb95a9bd7aab0f1601bc06455abfb"
},
{
"contractName": "CodeOracle",
Expand Down
116 changes: 90 additions & 26 deletions system-contracts/contracts/EvmEmulator.yul
Original file line number Diff line number Diff line change
Expand Up @@ -393,18 +393,33 @@ object "EvmEmulator" {
isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36)
}

// Basically performs an extcodecopy, while returning the length of the bytecode.
function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen {
// Basically performs an extcodecopy, while returning the length of the copied bytecode.
function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen {
let codeHash := getRawCodeHash(addr)
mstore(0, codeHash)
// The first word of returndata is the true length of the bytecode
codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32)
let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32)

if gt(len, codeLen) {
len := codeLen
}

returndatacopy(dstOffset, add(32, srcOffset), len)
let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length

let _returndatasize := returndatasize()
if gt(shiftedSrcOffset, _returndatasize) {
shiftedSrcOffset := _returndatasize
}

if gt(add(len, shiftedSrcOffset), _returndatasize) {
len := sub(_returndatasize, shiftedSrcOffset)
}

if len {
returndatacopy(dstOffset, shiftedSrcOffset, len)
}

copiedLen := len
}

// Returns the length of the EVM bytecode.
Expand Down Expand Up @@ -1571,6 +1586,10 @@ object "EvmEmulator" {

checkMemIsAccessible(destOffset, size)

if gt(offset, MAX_UINT64()) {
offset := MAX_UINT64()
}

// dynamicGas = 3 * minimum_word_size + memory_expansion_cost
// minimum_word_size = (size + 31) / 32
let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size))
Expand Down Expand Up @@ -1606,15 +1625,28 @@ object "EvmEmulator" {
evmGasLeft := chargeGas(evmGasLeft, dynamicGas)

dstOffset := add(dstOffset, MEM_OFFSET())

if gt(sourceOffset, MAX_UINT64()) {
sourceOffset := MAX_UINT64()
}

sourceOffset := add(sourceOffset, BYTECODE_OFFSET())

checkOverflow(sourceOffset, len)
// Check bytecode overflow
if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) {
panic()
if gt(sourceOffset, MEM_LEN_OFFSET()) {
sourceOffset := MEM_LEN_OFFSET()
}

$llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len)
// Check bytecode out-of-bounds access
let truncatedLen := len
if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) {
truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate
$llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds
}

if truncatedLen {
$llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, truncatedLen)
}

ip := add(ip, 1)
}
case 0x3A { // OP_GASPRICE
Expand Down Expand Up @@ -1672,14 +1704,14 @@ object "EvmEmulator" {
}

if gt(len, 0) {
let realCodeLen
let copiedLen
if getRawCodeHash(addr) {
// Gets the code from the addr
realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)
copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)
}

if lt(realCodeLen, len) {
$llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen))
if lt(copiedLen, len) {
$llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen))
}
}

Expand Down Expand Up @@ -3409,18 +3441,33 @@ object "EvmEmulator" {
isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36)
}

// Basically performs an extcodecopy, while returning the length of the bytecode.
function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen {
// Basically performs an extcodecopy, while returning the length of the copied bytecode.
function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen {
let codeHash := getRawCodeHash(addr)
mstore(0, codeHash)
// The first word of returndata is the true length of the bytecode
codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32)
let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32)

if gt(len, codeLen) {
len := codeLen
}

returndatacopy(dstOffset, add(32, srcOffset), len)
let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length

let _returndatasize := returndatasize()
if gt(shiftedSrcOffset, _returndatasize) {
shiftedSrcOffset := _returndatasize
}

if gt(add(len, shiftedSrcOffset), _returndatasize) {
len := sub(_returndatasize, shiftedSrcOffset)
}

if len {
returndatacopy(dstOffset, shiftedSrcOffset, len)
}

copiedLen := len
}

// Returns the length of the EVM bytecode.
Expand Down Expand Up @@ -4587,6 +4634,10 @@ object "EvmEmulator" {

checkMemIsAccessible(destOffset, size)

if gt(offset, MAX_UINT64()) {
offset := MAX_UINT64()
}

// dynamicGas = 3 * minimum_word_size + memory_expansion_cost
// minimum_word_size = (size + 31) / 32
let dynamicGas := add(mul(3, shr(5, add(size, 31))), expandMemory(destOffset, size))
Expand Down Expand Up @@ -4622,15 +4673,28 @@ object "EvmEmulator" {
evmGasLeft := chargeGas(evmGasLeft, dynamicGas)

dstOffset := add(dstOffset, MEM_OFFSET())

if gt(sourceOffset, MAX_UINT64()) {
sourceOffset := MAX_UINT64()
}

sourceOffset := add(sourceOffset, BYTECODE_OFFSET())

checkOverflow(sourceOffset, len)
// Check bytecode overflow
if gt(add(sourceOffset, len), sub(MEM_LEN_OFFSET(), 1)) {
panic()
if gt(sourceOffset, MEM_LEN_OFFSET()) {
sourceOffset := MEM_LEN_OFFSET()
}

$llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, len)
// Check bytecode out-of-bounds access
let truncatedLen := len
if gt(add(sourceOffset, len), MEM_LEN_OFFSET()) {
truncatedLen := sub(MEM_LEN_OFFSET(), sourceOffset) // truncate
$llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, truncatedLen), sub(len, truncatedLen)) // pad with zeroes any out-of-bounds
}

if truncatedLen {
$llvm_AlwaysInline_llvm$_memcpy(dstOffset, sourceOffset, truncatedLen)
}

ip := add(ip, 1)
}
case 0x3A { // OP_GASPRICE
Expand Down Expand Up @@ -4688,14 +4752,14 @@ object "EvmEmulator" {
}

if gt(len, 0) {
let realCodeLen
let copiedLen
if getRawCodeHash(addr) {
// Gets the code from the addr
realCodeLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)
copiedLen := fetchDeployedCode(addr, add(dstOffset, MEM_OFFSET()), srcOffset, len)
}

if lt(realCodeLen, len) {
$llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, realCodeLen), sub(len, realCodeLen))
if lt(copiedLen, len) {
$llvm_AlwaysInline_llvm$_memsetToZero(add(dstOffset, copiedLen), sub(len, copiedLen))
}
}

Expand Down
23 changes: 19 additions & 4 deletions system-contracts/evm-emulator/EvmEmulatorFunctions.template.yul
Original file line number Diff line number Diff line change
Expand Up @@ -331,18 +331,33 @@ function isEvmContract(addr) -> isEVM {
isEVM := fetchFromSystemContract(ACCOUNT_CODE_STORAGE_SYSTEM_CONTRACT(), 36)
}

// Basically performs an extcodecopy, while returning the length of the bytecode.
function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> codeLen {
// Basically performs an extcodecopy, while returning the length of the copied bytecode.
function fetchDeployedCode(addr, dstOffset, srcOffset, len) -> copiedLen {
let codeHash := getRawCodeHash(addr)
mstore(0, codeHash)
// The first word of returndata is the true length of the bytecode
codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32)
let codeLen := fetchFromSystemContract(CODE_ORACLE_SYSTEM_CONTRACT(), 32)

if gt(len, codeLen) {
len := codeLen
}

returndatacopy(dstOffset, add(32, srcOffset), len)
let shiftedSrcOffset := add(32, srcOffset) // first 32 bits is length

let _returndatasize := returndatasize()
if gt(shiftedSrcOffset, _returndatasize) {
shiftedSrcOffset := _returndatasize
}

if gt(add(len, shiftedSrcOffset), _returndatasize) {
len := sub(_returndatasize, shiftedSrcOffset)
}

if len {
returndatacopy(dstOffset, shiftedSrcOffset, len)
}

copiedLen := len
}

// Returns the length of the EVM bytecode.
Expand Down
Loading
Loading