Skip to content

Commit 290b1c3

Browse files
committed
Allow memory-safe inline assembly dialect flag.
1 parent 6b6e163 commit 290b1c3

File tree

6 files changed

+82
-4
lines changed

6 files changed

+82
-4
lines changed

libsolidity/analysis/DocStringTagParser.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,17 @@ bool DocStringTagParser::visit(InlineAssembly const& _assembly)
202202
if (valuesSeen.insert(value).second)
203203
{
204204
if (value == "memory-safe-assembly")
205+
{
206+
if (_assembly.annotation().markedMemorySafe)
207+
m_errorReporter.warning(
208+
8544_error,
209+
_assembly.location(),
210+
"Inline assembly marked as memory safe using both a NatSpec tag and an assembly flag. "
211+
"If you are not concerned with backwards compatibility, only use the assembly flag, "
212+
"otherwise only use the NatSpec tag."
213+
);
205214
_assembly.annotation().markedMemorySafe = true;
215+
}
206216
else
207217
m_errorReporter.warning(
208218
8787_error,

libsolidity/analysis/SyntaxChecker.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,27 @@ bool SyntaxChecker::visit(UnaryOperation const& _operation)
334334

335335
bool SyntaxChecker::visit(InlineAssembly const& _inlineAssembly)
336336
{
337+
if (_inlineAssembly.flags())
338+
for (auto flag: *_inlineAssembly.flags())
339+
{
340+
if (*flag == "memory-safe")
341+
{
342+
if (_inlineAssembly.annotation().markedMemorySafe)
343+
m_errorReporter.syntaxError(
344+
7026_error,
345+
_inlineAssembly.location(),
346+
"Inline assembly marked memory-safe multiple times."
347+
);
348+
_inlineAssembly.annotation().markedMemorySafe = true;
349+
}
350+
else
351+
m_errorReporter.warning(
352+
4430_error,
353+
_inlineAssembly.location(),
354+
"Unknown inline assembly flag: \"" + *flag + "\""
355+
);
356+
}
357+
337358
if (!m_useYulOptimizer)
338359
return false;
339360

libsolidity/ast/AST.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1463,19 +1463,26 @@ class InlineAssembly: public Statement
14631463
SourceLocation const& _location,
14641464
ASTPointer<ASTString> const& _docString,
14651465
yul::Dialect const& _dialect,
1466+
ASTPointer<std::vector<ASTPointer<ASTString>>> _flags,
14661467
std::shared_ptr<yul::Block> _operations
14671468
):
1468-
Statement(_id, _location, _docString), m_dialect(_dialect), m_operations(std::move(_operations)) {}
1469+
Statement(_id, _location, _docString),
1470+
m_dialect(_dialect),
1471+
m_flags(move(_flags)),
1472+
m_operations(std::move(_operations))
1473+
{}
14691474
void accept(ASTVisitor& _visitor) override;
14701475
void accept(ASTConstVisitor& _visitor) const override;
14711476

14721477
yul::Dialect const& dialect() const { return m_dialect; }
14731478
yul::Block const& operations() const { return *m_operations; }
1479+
ASTPointer<std::vector<ASTPointer<ASTString>>> const& flags() const { return m_flags; }
14741480

14751481
InlineAssemblyAnnotation& annotation() const override;
14761482

14771483
private:
14781484
yul::Dialect const& m_dialect;
1485+
ASTPointer<std::vector<ASTPointer<ASTString>>> m_flags;
14791486
std::shared_ptr<yul::Block> m_operations;
14801487
};
14811488

libsolidity/ast/ASTJsonConverter.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -600,11 +600,23 @@ bool ASTJsonConverter::visit(InlineAssembly const& _node)
600600
for (Json::Value& it: externalReferences | ranges::views::values)
601601
externalReferencesJson.append(std::move(it));
602602

603-
setJsonNode(_node, "InlineAssembly", {
603+
std::vector<pair<string, Json::Value>> attributes = {
604604
make_pair("AST", Json::Value(yul::AsmJsonConverter(sourceIndexFromLocation(_node.location()))(_node.operations()))),
605605
make_pair("externalReferences", std::move(externalReferencesJson)),
606606
make_pair("evmVersion", dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect()).evmVersion().name())
607-
});
607+
};
608+
609+
if (_node.flags())
610+
{
611+
Json::Value flags(Json::arrayValue);
612+
for (auto const& flag: *_node.flags())
613+
if (flag)
614+
flags.append(*flag);
615+
else
616+
flags.append(Json::nullValue);
617+
attributes.emplace_back(make_pair("flags", move(flags)));
618+
}
619+
setJsonNode(_node, "InlineAssembly", move(attributes));
608620

609621
return false;
610622
}

libsolidity/ast/ASTJsonImporter.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,11 +626,24 @@ ASTPointer<InlineAssembly> ASTJsonImporter::createInlineAssembly(Json::Value con
626626
astAssert(m_evmVersion == evmVersion, "Imported tree evm version differs from configured evm version!");
627627

628628
yul::Dialect const& dialect = yul::EVMDialect::strictAssemblyForEVM(evmVersion.value());
629+
ASTPointer<vector<ASTPointer<ASTString>>> flags;
630+
if (_node.isMember("flags"))
631+
{
632+
flags = make_shared<vector<ASTPointer<ASTString>>>();
633+
Json::Value const& flagsNode = _node["flags"];
634+
astAssert(flagsNode.isArray(), "Assembly flags must be an array.");
635+
for (Json::ArrayIndex i = 0; i < flagsNode.size(); ++i)
636+
{
637+
astAssert(flagsNode[i].isString(), "Assembly flag must be a string.");
638+
flags->emplace_back(make_shared<ASTString>(flagsNode[i].asString()));
639+
}
640+
}
629641
shared_ptr<yul::Block> operations = make_shared<yul::Block>(yul::AsmJsonImporter(m_sourceNames).createBlock(member(_node, "AST")));
630642
return createASTNode<InlineAssembly>(
631643
_node,
632644
nullOrASTString(_node, "documentation"),
633645
dialect,
646+
move(flags),
634647
operations
635648
);
636649
}

libsolidity/parsing/Parser.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1321,13 +1321,28 @@ ASTPointer<InlineAssembly> Parser::parseInlineAssembly(ASTPointer<ASTString> con
13211321
advance();
13221322
}
13231323

1324+
ASTPointer<vector<ASTPointer<ASTString>>> flags;
1325+
if (m_scanner->currentToken() == Token::LParen)
1326+
{
1327+
flags = make_shared<vector<ASTPointer<ASTString>>>();
1328+
do
1329+
{
1330+
advance();
1331+
expectToken(Token::StringLiteral, false);
1332+
flags->emplace_back(make_shared<ASTString>(m_scanner->currentLiteral()));
1333+
advance();
1334+
}
1335+
while (m_scanner->currentToken() == Token::Comma);
1336+
expectToken(Token::RParen);
1337+
}
1338+
13241339
yul::Parser asmParser(m_errorReporter, dialect);
13251340
shared_ptr<yul::Block> block = asmParser.parseInline(m_scanner);
13261341
if (block == nullptr)
13271342
BOOST_THROW_EXCEPTION(FatalError());
13281343

13291344
location.end = nativeLocationOf(*block).end;
1330-
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, block);
1345+
return make_shared<InlineAssembly>(nextID(), location, _docString, dialect, move(flags), block);
13311346
}
13321347

13331348
ASTPointer<IfStatement> Parser::parseIfStatement(ASTPointer<ASTString> const& _docString)

0 commit comments

Comments
 (0)