mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Check availability of data objects already in analysis phase.
This commit is contained in:
parent
f3bdc79187
commit
2a5280faa0
@ -18,6 +18,7 @@ Compiler Features:
|
||||
|
||||
Bugfixes:
|
||||
* View/Pure Checker: Properly detect state variable access through base class.
|
||||
* Yul analyzer: Check availability of data objects already in analysis phase.
|
||||
|
||||
|
||||
|
||||
|
@ -383,11 +383,19 @@ bool AsmAnalyzer::operator()(FunctionCall const& _funCall)
|
||||
{
|
||||
if (!expectExpression(arg))
|
||||
success = false;
|
||||
else if (needsLiteralArguments && arg.type() != typeid(Literal))
|
||||
m_errorReporter.typeError(
|
||||
_funCall.functionName.location,
|
||||
"Function expects direct literals as arguments."
|
||||
);
|
||||
else if (needsLiteralArguments)
|
||||
{
|
||||
if (arg.type() != typeid(Literal))
|
||||
m_errorReporter.typeError(
|
||||
_funCall.functionName.location,
|
||||
"Function expects direct literals as arguments."
|
||||
);
|
||||
else if (!m_dataNames.count(boost::get<Literal>(arg).value))
|
||||
m_errorReporter.typeError(
|
||||
_funCall.functionName.location,
|
||||
"Unknown data object \"" + boost::get<Literal>(arg).value.str() + "\"."
|
||||
);
|
||||
}
|
||||
}
|
||||
// Use argument size instead of parameter count to avoid misleading errors.
|
||||
m_stackHeight += int(returns) - int(_funCall.arguments.size());
|
||||
|
@ -61,13 +61,15 @@ public:
|
||||
langutil::ErrorReporter& _errorReporter,
|
||||
boost::optional<langutil::Error::Type> _errorTypeForLoose,
|
||||
Dialect const& _dialect,
|
||||
ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver()
|
||||
ExternalIdentifierAccess::Resolver const& _resolver = ExternalIdentifierAccess::Resolver(),
|
||||
std::set<YulString> const& _dataNames = {}
|
||||
):
|
||||
m_resolver(_resolver),
|
||||
m_info(_analysisInfo),
|
||||
m_errorReporter(_errorReporter),
|
||||
m_dialect(_dialect),
|
||||
m_errorTypeForLoose(_errorTypeForLoose)
|
||||
m_errorTypeForLoose(_errorTypeForLoose),
|
||||
m_dataNames(_dataNames)
|
||||
{
|
||||
if (EVMDialect const* evmDialect = dynamic_cast<EVMDialect const*>(&m_dialect))
|
||||
m_evmVersion = evmDialect->evmVersion();
|
||||
@ -124,6 +126,8 @@ private:
|
||||
langutil::EVMVersion m_evmVersion;
|
||||
Dialect const& m_dialect;
|
||||
boost::optional<langutil::Error::Type> m_errorTypeForLoose;
|
||||
/// Names of data objects to be referenced by builtin functions with literal arguments.
|
||||
std::set<YulString> m_dataNames;
|
||||
ForLoop const* m_currentForLoop = nullptr;
|
||||
};
|
||||
|
||||
|
@ -113,7 +113,20 @@ bool AssemblyStack::analyzeParsed(Object& _object)
|
||||
{
|
||||
solAssert(_object.code, "");
|
||||
_object.analysisInfo = make_shared<AsmAnalysisInfo>();
|
||||
AsmAnalyzer analyzer(*_object.analysisInfo, m_errorReporter, boost::none, languageToDialect(m_language, m_evmVersion));
|
||||
|
||||
set<YulString> objectNames;
|
||||
objectNames.insert(_object.name);
|
||||
for (auto const& subObject: _object.subIndexByName)
|
||||
objectNames.insert(subObject.first);
|
||||
|
||||
AsmAnalyzer analyzer(
|
||||
*_object.analysisInfo,
|
||||
m_errorReporter,
|
||||
boost::none,
|
||||
languageToDialect(m_language, m_evmVersion),
|
||||
{},
|
||||
objectNames
|
||||
);
|
||||
bool success = analyzer.analyze(*_object.code);
|
||||
for (auto& subNode: _object.subObjects)
|
||||
if (auto subObject = dynamic_cast<Object*>(subNode.get()))
|
||||
|
@ -278,6 +278,19 @@ BOOST_AUTO_TEST_CASE(args_to_datacopy_are_arbitrary)
|
||||
BOOST_CHECK(successParse(code));
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(non_existing_objects)
|
||||
{
|
||||
BOOST_CHECK(successParse(
|
||||
"object \"main\" { code { pop(datasize(\"main\")) } }"
|
||||
));
|
||||
CHECK_ERROR(
|
||||
"object \"main\" { code { pop(datasize(\"abc\")) } }",
|
||||
TypeError,
|
||||
"Unknown data object"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
@ -1,15 +1,18 @@
|
||||
{
|
||||
// Arguments to ``datasize`` and ``dataoffset`` need to be
|
||||
// literals. We cannot simplify their arguments, but we can
|
||||
// simplify them as a full expression.
|
||||
// ``datacopy`` does not have this restriction.
|
||||
let r := "abc"
|
||||
let a := datasize("abc")
|
||||
let x := dataoffset("abc")
|
||||
// should be replaced by a
|
||||
let y := datasize("abc")
|
||||
datacopy("abc", x, y)
|
||||
mstore(a, x)
|
||||
object "main" {
|
||||
code {
|
||||
// Arguments to ``datasize`` and ``dataoffset`` need to be
|
||||
// literals. We cannot simplify their arguments, but we can
|
||||
// simplify them as a full expression.
|
||||
// ``datacopy`` does not have this restriction.
|
||||
let r := "abc"
|
||||
let a := datasize("abc")
|
||||
let x := dataoffset("abc")
|
||||
// should be replaced by a
|
||||
let y := datasize("abc")
|
||||
datacopy("abc", x, y)
|
||||
mstore(a, x)
|
||||
}
|
||||
data "abc" "Hello, World!"
|
||||
}
|
||||
// ====
|
||||
// step: commonSubexpressionEliminator
|
||||
|
@ -1,10 +1,13 @@
|
||||
{
|
||||
// We should never split arguments to ``dataoffset``
|
||||
// or ``datasize`` because they need to be literals
|
||||
let x := dataoffset("abc")
|
||||
let y := datasize("abc")
|
||||
// datacopy is fine, though
|
||||
datacopy(mload(0), mload(1), mload(2))
|
||||
object "main" {
|
||||
code {
|
||||
// We should never split arguments to ``dataoffset``
|
||||
// or ``datasize`` because they need to be literals
|
||||
let x := dataoffset("abc")
|
||||
let y := datasize("abc")
|
||||
// datacopy is fine, though
|
||||
datacopy(mload(0), mload(1), mload(2))
|
||||
}
|
||||
data "abc" "Hello, World!"
|
||||
}
|
||||
// ====
|
||||
// step: expressionSplitter
|
||||
|
Loading…
Reference in New Issue
Block a user