diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 78af6306e..540086756 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -2245,7 +2245,6 @@ string YulUtilFunctions::readFromMemoryOrCalldata(Type const& _type, bool _fromC } solAssert(_type.isValueType(), ""); - if (auto const* funType = dynamic_cast(&_type)) if (funType->kind() == FunctionType::Kind::External) return Whiskers(R"( @@ -2259,18 +2258,23 @@ string YulUtilFunctions::readFromMemoryOrCalldata(Type const& _type, bool _fromC ("splitFunction", splitExternalFunctionIdFunction()) .render(); + return Whiskers(R"( - function (memPtr) -> value { - value := (memPtr) - + function (ptr) -> value { + + value := calldataload(ptr) (value) - + + value := (mload(ptr)) + } )") ("functionName", functionName) - ("load", _fromCalldata ? "calldataload" : "mload") - ("needsValidation", _fromCalldata) - ("validate", _fromCalldata ? validatorFunction(_type) : "") + ("fromCalldata", _fromCalldata) + ("validate", validatorFunction(_type)) + // Byte array elements generally need cleanup. + // Other types are cleaned as well to account for dirty memory e.g. due to inline assembly. + ("cleanup", cleanupFunction(_type)) .render(); }); } diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index 4f7556f5f..9f21a7d39 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -204,7 +204,7 @@ public: std::string readFromStorage(Type const& _type, size_t _offset, bool _splitFunctionTypes); std::string readFromStorageDynamic(Type const& _type, bool _splitFunctionTypes); - /// @returns a function that reads a value type from memory. + /// @returns a function that reads a value type from memory. Performs cleanup. /// signature: (addr) -> value std::string readFromMemory(Type const& _type); /// @returns a function that reads a value type from calldata. diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 31bbaf6e9..d10ec3bd5 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -117,10 +117,12 @@ struct CopyTranslate: public yul::ASTCopier reference.isOffset == false && reference.isSlot == false, "Should not be called for offset/slot" ); + auto const& var = m_context.localVariable(*varDecl); + solAssert(var.type().sizeOnStack() == 1, ""); return yul::Identifier{ _identifier.location, - yul::YulString{m_context.localVariable(*varDecl).name()} + yul::YulString{var.commaSeparatedList()} }; } @@ -2080,13 +2082,7 @@ IRVariable IRGeneratorForStatements::readFromLValue(IRLValue const& _lvalue) ")\n"; }, [&](IRLValue::Memory const& _memory) { - if (_memory.byteArrayElement) - define(result) << - m_utils.cleanupFunction(_lvalue.type) << - "(mload(" << - _memory.address << - "))\n"; - else if (_lvalue.type.isValueType()) + if (_lvalue.type.isValueType()) define(result) << m_utils.readFromMemory(_lvalue.type) << "(" << diff --git a/test/libsolidity/semanticTests/viaYul/dirty_memory_read.sol b/test/libsolidity/semanticTests/viaYul/dirty_memory_read.sol new file mode 100644 index 000000000..d03aa489f --- /dev/null +++ b/test/libsolidity/semanticTests/viaYul/dirty_memory_read.sol @@ -0,0 +1,15 @@ +contract C { + function f() public pure returns (uint8 x, bool a, bool b) { + uint8[1] memory m; + assembly { + mstore(m, 257) + } + x = m[0]; + a = (m[0] == 0x01); + b = (m[0] == 0x0101); + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 1, true, false