Skip to content

Commit a4c94a1

Browse files
committed
Fixed inline assembly external identifier access.
1 parent cc4e24c commit a4c94a1

File tree

7 files changed

+61
-3
lines changed

7 files changed

+61
-3
lines changed

libsolidity/analysis/TypeChecker.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,8 +742,15 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
742742
yul::Identifier const& _identifier,
743743
yul::IdentifierContext _context,
744744
bool
745-
)
745+
) -> bool
746746
{
747+
if (_context == yul::IdentifierContext::NonExternal)
748+
{
749+
// Hack until we can disallow any shadowing: If we found an internal reference,
750+
// clear the external references, so that codegen does not use it.
751+
_inlineAssembly.annotation().externalReferences.erase(& _identifier);
752+
return false;
753+
}
747754
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
748755
if (ref == _inlineAssembly.annotation().externalReferences.end())
749756
return false;

libsolidity/codegen/CompilerContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,7 @@ void CompilerContext::appendInlineAssembly(
411411
yul::AbstractAssembly& _assembly
412412
)
413413
{
414+
solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, "");
414415
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
415416
solAssert(it != _localVariables.end(), "");
416417
auto stackDepth = static_cast<size_t>(distance(it, _localVariables.end()));

libsolidity/codegen/ContractCompiler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
708708
yul::AbstractAssembly& _assembly
709709
)
710710
{
711+
solAssert(_context == yul::IdentifierContext::RValue || _context == yul::IdentifierContext::LValue, "");
711712
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
712713
solAssert(ref != _inlineAssembly.annotation().externalReferences.end(), "");
713714
Declaration const* decl = ref->second.declaration;

libyul/AsmAnalysis.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
146146
}
147147
}))
148148
{
149+
if (m_resolver)
150+
// We found a local reference, make sure there is no external reference.
151+
m_resolver(
152+
_identifier,
153+
yul::IdentifierContext::NonExternal,
154+
m_currentScope->insideFunction()
155+
);
149156
}
150157
else
151158
{
@@ -308,7 +315,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
308315

309316
validateInstructions(_funCall);
310317
}
311-
else if (!m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
318+
else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
312319
[&](Scope::Variable const&)
313320
{
314321
m_errorReporter.typeError(
@@ -323,6 +330,16 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
323330
returnTypes = &_fun.returns;
324331
}
325332
}))
333+
{
334+
if (m_resolver)
335+
// We found a local reference, make sure there is no external reference.
336+
m_resolver(
337+
_funCall.functionName,
338+
yul::IdentifierContext::NonExternal,
339+
m_currentScope->insideFunction()
340+
);
341+
}
342+
else
326343
{
327344
if (!validateInstructions(_funCall))
328345
m_errorReporter.declarationError(
@@ -539,6 +556,14 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
539556
bool found = false;
540557
if (Scope::Identifier const* var = m_currentScope->lookup(_variable.name))
541558
{
559+
if (m_resolver)
560+
// We found a local reference, make sure there is no external reference.
561+
m_resolver(
562+
_variable,
563+
yul::IdentifierContext::NonExternal,
564+
m_currentScope->insideFunction()
565+
);
566+
542567
if (!holds_alternative<Scope::Variable>(*var))
543568
m_errorReporter.typeError(2657_error, _variable.debugData->location, "Assignment requires variable.");
544569
else if (!m_activeVariables.count(&std::get<Scope::Variable>(*var)))

libyul/backends/evm/AbstractAssembly.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ class AbstractAssembly
117117
virtual void markAsInvalid() = 0;
118118
};
119119

120-
enum class IdentifierContext { LValue, RValue, VariableDeclaration };
120+
enum class IdentifierContext { LValue, RValue, VariableDeclaration, NonExternal };
121121

122122
/// Object that is used to resolve references and generate code for access to identifiers external
123123
/// to inline assembly (not used in standalone assembly mode).
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
contract C {
2+
function f() public returns (uint x) {
3+
assembly {
4+
function g() -> f { f := 2 }
5+
x := g()
6+
}
7+
}
8+
}
9+
// ====
10+
// compileViaYul: also
11+
// ----
12+
// f() -> 2
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
contract C {
2+
function f() public returns (uint x) {
3+
assembly {
4+
function g() -> x {
5+
x := 42
6+
}
7+
x := g()
8+
}
9+
}
10+
}
11+
// ----
12+
// DeclarationError 6578: (123-124): Cannot access local Solidity variables from inside an inline assembly function.

0 commit comments

Comments
 (0)