Check that there is an interface type before querying validity of location.

This commit is contained in:
Kamil Śliwak 2021-02-23 16:43:29 +01:00 committed by chriseth
parent 58e0977647
commit e87cd0afdf
4 changed files with 25 additions and 2 deletions

View File

@ -583,13 +583,18 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
if (auto referenceType = dynamic_cast<ReferenceType const*>(varType))
{
auto result = referenceType->validForLocation(referenceType->location());
BoolResult result = referenceType->validForLocation(referenceType->location());
if (result)
{
bool isLibraryStorageParameter = (_variable.isLibraryFunctionParameter() && referenceType->location() == DataLocation::Storage);
bool callDataCheckRequired = ((_variable.isConstructorParameter() || _variable.isPublicCallableParameter()) && !isLibraryStorageParameter);
if (callDataCheckRequired)
result = referenceType->validForLocation(DataLocation::CallData);
{
if (!referenceType->interfaceType(false))
solAssert(m_errorReporter.hasErrors(), "");
else
result = referenceType->validForLocation(DataLocation::CallData);
}
}
if (!result)
{

View File

@ -769,6 +769,8 @@ public:
bool isPointer() const;
/// @returns true if this is valid to be stored in data location _loc
/// The function mostly checks sizes. For calldata, this should only be called
/// if the type has an interfaceType.
virtual BoolResult validForLocation(DataLocation _loc) const = 0;
bool operator==(ReferenceType const& _other) const

View File

@ -0,0 +1,8 @@
pragma abicoder v2;
contract C {
struct S { function() internal a; }
function f(S[2] memory) public {}
}
// ----
// TypeError 4103: (89-100): Internal type is not allowed for public or external functions.

View File

@ -0,0 +1,8 @@
pragma abicoder v2;
contract C {
struct S { function() internal[2] a; }
function f(S memory) public {}
}
// ----
// TypeError 4103: (92-100): Internal type is not allowed for public or external functions.