Encode storage items correctly for library calls.

This commit is contained in:
chriseth 2015-10-04 11:05:57 +02:00
parent 421dcf4c1a
commit ce25ddfa6a
3 changed files with 36 additions and 2 deletions

View File

@ -189,7 +189,14 @@ void CompilerUtils::encodeToMemory(
copyToStackTop(argSize - stackPos + dynPointers + 2, _givenTypes[i]->sizeOnStack());
solAssert(!!targetType, "Externalable type expected.");
TypePointer type = targetType;
if (
if (_givenTypes[i]->dataStoredIn(DataLocation::Storage) && targetType->isValueType())
{
// special case: convert storage reference type to value type - this is only
// possible for library calls where we just forward the storage reference
solAssert(_encodeAsLibraryTypes, "");
solAssert(_givenTypes[i]->sizeOnStack() == 1, "");
}
else if (
_givenTypes[i]->dataStoredIn(DataLocation::Storage) ||
_givenTypes[i]->dataStoredIn(DataLocation::CallData) ||
_givenTypes[i]->category() == Type::Category::StringLiteral

View File

@ -1179,7 +1179,8 @@ void ExpressionCompiler::appendExternalFunctionCall(
argumentTypes,
_functionType.parameterTypes(),
_functionType.padArguments(),
_functionType.takesArbitraryParameters()
_functionType.takesArbitraryParameters(),
isCallCode
);
// Stack now:

View File

@ -5383,6 +5383,32 @@ BOOST_AUTO_TEST_CASE(internal_types_in_library)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17)));
}
BOOST_AUTO_TEST_CASE(differentiate_storage_and_memory_in_libraries)
{
char const* sourceCode = R"(
library Lib {
function f(uint[] storage x) returns (uint) { return 1; }
function f(uint[] memory x) returns (uint) { return 2; }
}
contract Test {
uint[] data;
function f() returns (uint a,)
{
uint[] memory d = data;
Lib.f(d)
data["abc"].length = 20;
data["abc"][4] = 9;
data["abc"][17] = 3;
a = Lib.find(data["abc"], 9);
b = Lib.find(data["abc"], 3);
}
}
)";
compileAndRun(sourceCode, 0, "Lib");
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"Lib", m_contractAddress}});
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(4), u256(17)));
}
BOOST_AUTO_TEST_CASE(short_strings)
{
// This test verifies that the byte array encoding that combines length and data works