mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Inaccessible dynamic types
This commit is contained in:
parent
7dab890278
commit
754a992500
@ -2037,29 +2037,20 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound)
|
||||
location = Location::DelegateCall;
|
||||
}
|
||||
|
||||
TypePointers returnParameterTypes;
|
||||
vector<string> returnParameterNames;
|
||||
if (location == Location::Internal)
|
||||
TypePointers returnParameterTypes = m_returnParameterTypes;
|
||||
if (location != Location::Internal)
|
||||
{
|
||||
returnParameterNames = m_returnParameterNames;
|
||||
returnParameterTypes = m_returnParameterTypes;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Removes dynamic types.
|
||||
for (size_t i = 0; i < m_returnParameterTypes.size(); ++i)
|
||||
if (!m_returnParameterTypes[i]->isDynamicallySized())
|
||||
{
|
||||
returnParameterTypes.push_back(m_returnParameterTypes[i]);
|
||||
returnParameterNames.push_back(m_returnParameterNames[i]);
|
||||
}
|
||||
// Alter dynamic types to be non-accessible.
|
||||
for (auto& param: returnParameterTypes)
|
||||
if (param->isDynamicallySized())
|
||||
param = make_shared<InaccessibleDynamicType>();
|
||||
}
|
||||
|
||||
return make_shared<FunctionType>(
|
||||
parameterTypes,
|
||||
returnParameterTypes,
|
||||
m_parameterNames,
|
||||
returnParameterNames,
|
||||
m_returnParameterNames,
|
||||
location,
|
||||
m_arbitraryParameters,
|
||||
m_declaration,
|
||||
|
@ -137,7 +137,8 @@ public:
|
||||
{
|
||||
Integer, RationalNumber, StringLiteral, Bool, FixedPoint, Array,
|
||||
FixedBytes, Contract, Struct, Function, Enum, Tuple,
|
||||
Mapping, TypeType, Modifier, Magic, Module
|
||||
Mapping, TypeType, Modifier, Magic, Module,
|
||||
InaccessibleDynamic
|
||||
};
|
||||
|
||||
/// @{
|
||||
@ -1081,5 +1082,25 @@ private:
|
||||
Kind m_kind;
|
||||
};
|
||||
|
||||
/**
|
||||
* Special type that is used for dynamic types in returns from external function calls
|
||||
* (The EVM currently cannot access dynamically-sized return values).
|
||||
*/
|
||||
class InaccessibleDynamicType: public Type
|
||||
{
|
||||
public:
|
||||
virtual Category category() const override { return Category::InaccessibleDynamic; }
|
||||
|
||||
virtual bool isImplicitlyConvertibleTo(Type const&) const override { return false; }
|
||||
virtual bool isExplicitlyConvertibleTo(Type const&) const override { return false; }
|
||||
virtual unsigned calldataEncodedSize(bool _padded) const override { (void)_padded; return 32; }
|
||||
virtual bool canBeStored() const override { return false; }
|
||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||
virtual bool isValueType() const override { return true; }
|
||||
virtual unsigned sizeOnStack() const override { return 1; }
|
||||
virtual std::string toString(bool) const override { return "inaccessible dynamic type"; }
|
||||
virtual TypePointer decodingType() const override { return std::make_shared<IntegerType>(256); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -6793,6 +6793,25 @@ BOOST_AUTO_TEST_CASE(cleanup_bytes_types)
|
||||
BOOST_CHECK(callContractFunction("f(bytes2,uint16)", string("abc"), u256(0x040102)) == encodeArgs(0));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(skip_dynamic_types)
|
||||
{
|
||||
// The EVM cannot provide access to dynamically-sized return values, so we have to skip them.
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f() returns (uint, uint[], uint) {
|
||||
return (7, new uint[](2), 8);
|
||||
}
|
||||
function g() returns (uint, uint) {
|
||||
// Previous implementation "moved" b to the second place and did not skip.
|
||||
var (a, _, b) = this.f();
|
||||
return (a, b);
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode, 0, "C");
|
||||
BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(7), u256(8)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -2154,6 +2154,8 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible)
|
||||
function f(uint) returns (string);
|
||||
function g() {
|
||||
var (x,) = this.f(2);
|
||||
// we can assign to x but it is not usable.
|
||||
bytes(x).length;
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
Loading…
Reference in New Issue
Block a user