Skip to content

Commit 45aa971

Browse files
authored
fix: never expand memory when access size is 0 (#245)
1 parent 972cb6c commit 45aa971

1 file changed

Lines changed: 76 additions & 42 deletions

File tree

src/compiler/evm_frontend/evm_imported.cpp

Lines changed: 76 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -574,12 +574,15 @@ void evmSetMCopy(zen::runtime::EVMInstance *Instance, uint64_t Dest,
574574
}
575575
void evmSetReturn(zen::runtime::EVMInstance *Instance, uint64_t Offset,
576576
uint64_t Len) {
577-
if (!Instance->expandMemoryChecked(Offset, Len)) {
578-
return;
577+
std::vector<uint8_t> ReturnData;
578+
if (Len > 0) {
579+
if (!Instance->expandMemoryChecked(Offset, Len)) {
580+
return;
581+
}
582+
auto &Memory = Instance->getMemory();
583+
ReturnData = std::vector<uint8_t>(Memory.begin() + Offset,
584+
Memory.begin() + Offset + Len);
579585
}
580-
auto &Memory = Instance->getMemory();
581-
std::vector<uint8_t> ReturnData(Memory.begin() + Offset,
582-
Memory.begin() + Offset + Len);
583586
Instance->setReturnData(ReturnData);
584587

585588
evmc::Result ExeResult(EVMC_SUCCESS, 0,
@@ -591,6 +594,10 @@ void evmSetReturn(zen::runtime::EVMInstance *Instance, uint64_t Offset,
591594
}
592595
void evmSetCallDataCopy(zen::runtime::EVMInstance *Instance,
593596
uint64_t DestOffset, uint64_t Offset, uint64_t Size) {
597+
// When Size is 0, no memory operations are needed
598+
if (Size == 0) {
599+
return;
600+
}
594601
if (!Instance->expandMemoryChecked(DestOffset, Size)) {
595602
return;
596603
}
@@ -626,23 +633,27 @@ void evmSetCallDataCopy(zen::runtime::EVMInstance *Instance,
626633
void evmSetExtCodeCopy(zen::runtime::EVMInstance *Instance,
627634
const uint8_t *Address, uint64_t DestOffset,
628635
uint64_t Offset, uint64_t Size) {
629-
if (!Instance->expandMemoryChecked(DestOffset, Size)) {
630-
return;
631-
}
632-
if (uint64_t CopyGas = calculateWordCopyGas(Size)) {
633-
Instance->chargeGas(CopyGas);
634-
}
635-
636636
const zen::runtime::EVMModule *Module = Instance->getModule();
637637
ZEN_ASSERT(Module && Module->Host);
638638
evmc::address Addr = loadAddressFromLE(Address);
639-
640639
evmc_revision Rev = Instance->getRevision();
641640
if (Rev >= EVMC_BERLIN &&
642641
Module->Host->access_account(Addr) == EVMC_ACCESS_COLD) {
643642
Instance->chargeGas(zen::evm::ADDITIONAL_COLD_ACCOUNT_ACCESS_COST);
644643
}
645644

645+
// When Size is 0, no memory operations are needed
646+
if (Size == 0) {
647+
return;
648+
}
649+
650+
if (!Instance->expandMemoryChecked(DestOffset, Size)) {
651+
return;
652+
}
653+
if (uint64_t CopyGas = calculateWordCopyGas(Size)) {
654+
Instance->chargeGas(CopyGas);
655+
}
656+
646657
auto &Memory = Instance->getMemory();
647658
size_t CodeSize = Module->Host->get_code_size(Addr);
648659

@@ -665,6 +676,10 @@ void evmSetExtCodeCopy(zen::runtime::EVMInstance *Instance,
665676

666677
void evmSetReturnDataCopy(zen::runtime::EVMInstance *Instance,
667678
uint64_t DestOffset, uint64_t Offset, uint64_t Size) {
679+
// When Size is 0, no memory operations are needed
680+
if (Size == 0) {
681+
return;
682+
}
668683
if (!Instance->expandMemoryChecked(DestOffset, Size)) {
669684
return;
670685
}
@@ -705,14 +720,16 @@ static void evmEmitLogGeneric(zen::runtime::EVMInstance *Instance,
705720
const evmc_message *Msg = Instance->getCurrentMessage();
706721
ZEN_ASSERT(Msg && "No current message set in EVMInstance");
707722

708-
// Calculate required memory size and charge gas
709-
if (!Instance->expandMemoryChecked(Offset, Size)) {
710-
return;
723+
// Only expand memory if we actually need to access it (Size > 0)
724+
const uint8_t *Data = nullptr;
725+
if (Size > 0) {
726+
if (!Instance->expandMemoryChecked(Offset, Size)) {
727+
return;
728+
}
729+
auto &Memory = Instance->getMemory();
730+
Data = Memory.data() + Offset;
711731
}
712732

713-
auto &Memory = Instance->getMemory();
714-
const uint8_t *Data = Memory.data() + Offset;
715-
716733
// Build topic array - only include non-null topics
717734
evmc::bytes32 Topics[MaxTopics] = {};
718735
size_t ActualNumTopics = 0;
@@ -805,13 +822,16 @@ const uint8_t *evmHandleCreateInternal(zen::runtime::EVMInstance *Instance,
805822
}
806823

807824
// Calculate required memory size and charge gas
808-
if (!Instance->expandMemoryChecked(Offset, Size)) {
809-
Instance->setReturnData({});
810-
return ZeroAddress;
811-
}
825+
const uint8_t *InitCode = nullptr;
826+
if (Size > 0) {
827+
if (!Instance->expandMemoryChecked(Offset, Size)) {
828+
Instance->setReturnData({});
829+
return ZeroAddress;
830+
}
812831

813-
auto &Memory = Instance->getMemory();
814-
const uint8_t *InitCode = Memory.data() + Offset;
832+
auto &Memory = Instance->getMemory();
833+
InitCode = Memory.data() + Offset;
834+
}
815835

816836
// Create message for CREATE/CREATE2
817837
evmc_message CreateMsg = {};
@@ -928,10 +948,15 @@ static uint64_t evmHandleCallInternal(zen::runtime::EVMInstance *Instance,
928948
}
929949

930950
// Calculate required memory sizes for input and output
931-
if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize, RetOffset,
932-
RetSize)) {
933-
Instance->setReturnData({});
934-
return 0;
951+
// Only expand memory if we actually need to access it
952+
bool needArgsMemory = ArgsSize > 0;
953+
bool needRetMemory = RetSize > 0;
954+
if (needArgsMemory || needRetMemory) {
955+
if (!Instance->expandMemoryChecked(ArgsOffset, ArgsSize, RetOffset,
956+
RetSize)) {
957+
Instance->setReturnData({});
958+
return 0;
959+
}
935960
}
936961

937962
auto &Memory = Instance->getMemory();
@@ -1088,12 +1113,15 @@ uint64_t evmHandleStaticCall(zen::runtime::EVMInstance *Instance, uint64_t Gas,
10881113

10891114
void evmSetRevert(zen::runtime::EVMInstance *Instance, uint64_t Offset,
10901115
uint64_t Size) {
1091-
if (!Instance->expandMemoryChecked(Offset, Size)) {
1092-
return;
1116+
std::vector<uint8_t> ReturnData;
1117+
if (Size > 0) {
1118+
if (!Instance->expandMemoryChecked(Offset, Size)) {
1119+
return;
1120+
}
1121+
auto &Memory = Instance->getMemory();
1122+
ReturnData = std::vector<uint8_t>(Memory.begin() + Offset,
1123+
Memory.begin() + Offset + Size);
10931124
}
1094-
auto &Memory = Instance->getMemory();
1095-
std::vector<uint8_t> ReturnData(Memory.begin() + Offset,
1096-
Memory.begin() + Offset + Size);
10971125
Instance->setReturnData(std::move(ReturnData));
10981126
const int64_t GasLeft =
10991127
Instance ? static_cast<int64_t>(Instance->getGas()) : 0;
@@ -1107,6 +1135,10 @@ void evmSetRevert(zen::runtime::EVMInstance *Instance, uint64_t Offset,
11071135

11081136
void evmSetCodeCopy(zen::runtime::EVMInstance *Instance, uint64_t DestOffset,
11091137
uint64_t Offset, uint64_t Size) {
1138+
// When Size is 0, no memory operations are needed
1139+
if (Size == 0) {
1140+
return;
1141+
}
11101142
if (!Instance->expandMemoryChecked(DestOffset, Size)) {
11111143
return;
11121144
}
@@ -1136,15 +1168,17 @@ void evmSetCodeCopy(zen::runtime::EVMInstance *Instance, uint64_t DestOffset,
11361168

11371169
const uint8_t *evmGetKeccak256(zen::runtime::EVMInstance *Instance,
11381170
uint64_t Offset, uint64_t Length) {
1139-
if (!Instance->expandMemoryChecked(Offset, Length)) {
1140-
return nullptr;
1171+
const uint8_t *InputData = nullptr;
1172+
if (Length > 0) {
1173+
if (!Instance->expandMemoryChecked(Offset, Length)) {
1174+
return nullptr;
1175+
}
1176+
const uint64_t ExtraGas =
1177+
static_cast<uint64_t>(numWords(static_cast<uint64_t>(Length))) * 6;
1178+
Instance->chargeGas(ExtraGas);
1179+
auto &Memory = Instance->getMemory();
1180+
InputData = Memory.data() + Offset;
11411181
}
1142-
const uint64_t ExtraGas =
1143-
static_cast<uint64_t>(numWords(static_cast<uint64_t>(Length))) * 6;
1144-
Instance->chargeGas(ExtraGas);
1145-
1146-
auto &Memory = Instance->getMemory();
1147-
const uint8_t *InputData = Memory.data() + Offset;
11481182

11491183
auto &Cache = Instance->getMessageCache();
11501184
evmc::bytes32 HashResult;

0 commit comments

Comments
 (0)