Merge pull request #11741 from ethereum/shadowing_inlineasm_fix_yul_codegen

Fixed inline assembly external identifier access.
This commit is contained in:
chriseth 2021-08-12 14:38:24 +02:00 committed by GitHub
commit ccdc11ea5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 61 additions and 3 deletions

View File

@ -742,8 +742,15 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
yul::Identifier const& _identifier,
yul::IdentifierContext _context,
bool
)
) -> bool
{
if (_context == yul::IdentifierContext::NonExternal)
{
// Hack until we can disallow any shadowing: If we found an internal reference,
// clear the external references, so that codegen does not use it.
_inlineAssembly.annotation().externalReferences.erase(& _identifier);
return false;
}
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
if (ref == _inlineAssembly.annotation().externalReferences.end())
return false;

View File

@ -411,6 +411,7 @@ void CompilerContext::appendInlineAssembly(
yul::AbstractAssembly& _assembly
)
{
solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, "");
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
solAssert(it != _localVariables.end(), "");
auto stackDepth = static_cast<size_t>(distance(it, _localVariables.end()));

View File

@ -708,6 +708,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
yul::AbstractAssembly& _assembly
)
{
solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, "");
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
solAssert(ref != _inlineAssembly.annotation().externalReferences.end(), "");
Declaration const* decl = ref->second.declaration;

View File

@ -146,6 +146,13 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
}
}))
{
if (m_resolver)
// We found a local reference, make sure there is no external reference.
m_resolver(
_identifier,
yul::IdentifierContext::NonExternal,
m_currentScope->insideFunction()
);
}
else
{
@ -308,7 +315,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
validateInstructions(_funCall);
}
else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
[&](Scope::Variable const&)
{
m_errorReporter.typeError(
@ -323,6 +330,16 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
returnTypes = &_fun.returns;
}
}))
{
if (m_resolver)
// We found a local reference, make sure there is no external reference.
m_resolver(
_funCall.functionName,
yul::IdentifierContext::NonExternal,
m_currentScope->insideFunction()
);
}
else
{
if (!validateInstructions(_funCall))
m_errorReporter.declarationError(
@ -539,6 +556,14 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
bool found = false;
if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
{
if (m_resolver)
// We found a local reference, make sure there is no external reference.
m_resolver(
_variable,
yul::IdentifierContext::NonExternal,
m_currentScope->insideFunction()
);
if (!holds_alternative<Scope::Variable>(*var))
m_errorReporter.typeError(2657_error, _variable.debugData->location, "Assignment requires variable.");
else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var)))

View File

@ -117,7 +117,7 @@ public:
virtual void markAsInvalid() = 0;
};
enum class IdentifierContext { LValue, RValue, VariableDeclaration };
enum class IdentifierContext { LValue, RValue, VariableDeclaration, NonExternal };
/// Object that is used to resolve references and generate code for access to identifiers external
/// to inline assembly (not used in standalone assembly mode).

View File

@ -0,0 +1,12 @@
contract C {
function f() public returns (uint x) {
assembly {
function g() -> f { f := 2 }
x := g()
}
}
}
// ====
// compileViaYul: also
// ----
// f() -> 2

View File

@ -0,0 +1,12 @@
contract C {
function f() public returns (uint x) {
assembly {
function g() -> x {
x := 42
}
x := g()
}
}
}
// ----
// DeclarationError 6578: (123-124): Cannot access local Solidity variables from inside an inline assembly function.