mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Inline assembly without memory effects is implicitly memory safe.
This commit is contained in:
parent
e6848caac1
commit
9bcfcc61a7
@ -202,7 +202,7 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly)
|
||||
if (valuesSeen.insert(value).second)
|
||||
{
|
||||
if (value == "memory-safe-assembly")
|
||||
_assembly.annotation().memorySafe = true;
|
||||
_assembly.annotation().markedMemorySafe = true;
|
||||
else
|
||||
m_errorReporter.warning(
|
||||
8787_error,
|
||||
|
@ -763,6 +763,7 @@ void TypeChecker::endVisit(FunctionTypeName const& _funType)
|
||||
|
||||
bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
{
|
||||
bool lvalueAccessToMemoryVariable = false;
|
||||
// External references have already been resolved in a prior stage and stored in the annotation.
|
||||
// We run the resolve step again regardless.
|
||||
yul::ExternalIdentifierAccess::Resolver identifierAccess = [&](
|
||||
@ -787,6 +788,8 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
if (auto var = dynamic_cast<VariableDeclaration const*>(declaration))
|
||||
{
|
||||
solAssert(var->type(), "Expected variable type!");
|
||||
if (_context == yul::IdentifierContext::LValue && var->type()->dataStoredIn(DataLocation::Memory))
|
||||
lvalueAccessToMemoryVariable = true;
|
||||
if (var->immutable())
|
||||
{
|
||||
m_errorReporter.typeError(3773_error, nativeLocationOf(_identifier), "Assembly access to immutable variables is not supported.");
|
||||
@ -974,8 +977,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
|
||||
identifierAccess
|
||||
);
|
||||
if (!analyzer.analyze(_inlineAssembly.operations()))
|
||||
return false;
|
||||
return true;
|
||||
solAssert(m_errorReporter.hasErrors());
|
||||
_inlineAssembly.annotation().hasMemoryEffects =
|
||||
lvalueAccessToMemoryVariable ||
|
||||
(analyzer.sideEffects().memory != yul::SideEffects::None);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeChecker::visit(IfStatement const& _ifStatement)
|
||||
|
@ -221,7 +221,9 @@ struct InlineAssemblyAnnotation: StatementAnnotation
|
||||
/// Information generated during analysis phase.
|
||||
std::shared_ptr<yul::AsmAnalysisInfo> analysisInfo;
|
||||
/// True, if the assembly block was annotated to be memory-safe.
|
||||
bool memorySafe = false;
|
||||
bool markedMemorySafe = false;
|
||||
/// True, if the assembly block involves any memory opcode or assigns to variables in memory.
|
||||
SetOnce<bool> hasMemoryEffects;
|
||||
};
|
||||
|
||||
struct BlockAnnotation: StatementAnnotation, ScopableAnnotation
|
||||
|
@ -2138,7 +2138,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
||||
bool IRGeneratorForStatements::visit(InlineAssembly const& _inlineAsm)
|
||||
{
|
||||
setLocation(_inlineAsm);
|
||||
if (!_inlineAsm.annotation().memorySafe)
|
||||
if (*_inlineAsm.annotation().hasMemoryEffects && !_inlineAsm.annotation().markedMemorySafe)
|
||||
m_context.setMemoryUnsafeInlineAssemblySeen();
|
||||
CopyTranslate bodyCopier{_inlineAsm.dialect(), m_context, _inlineAsm.annotation().externalReferences};
|
||||
|
||||
|
@ -316,6 +316,7 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
literalArguments = &f->literalArguments;
|
||||
|
||||
validateInstructions(_funCall);
|
||||
m_sideEffects += f->sideEffects;
|
||||
}
|
||||
else if (m_currentScope->lookup(_funCall.functionName.name, GenericVisitor{
|
||||
[&](Scope::Variable const&)
|
||||
|
@ -94,6 +94,8 @@ public:
|
||||
void operator()(Leave const&) { }
|
||||
void operator()(Block const& _block);
|
||||
|
||||
/// @returns the worst side effects encountered during analysis (including within defined functions).
|
||||
SideEffects const& sideEffects() const { return m_sideEffects; }
|
||||
private:
|
||||
/// Visits the expression, expects that it evaluates to exactly one value and
|
||||
/// returns the type. Reports errors on errors and returns the default type.
|
||||
@ -128,6 +130,8 @@ private:
|
||||
/// Names of data objects to be referenced by builtin functions with literal arguments.
|
||||
std::set<YulString> m_dataNames;
|
||||
ForLoop const* m_currentForLoop = nullptr;
|
||||
/// Worst side effects encountered during analysis (including within defined functions).
|
||||
SideEffects m_sideEffects;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user