Allow Yul literals longer than 32-bytes when used as literal arguments for builtins

This commit is contained in:
Kamil Śliwak 2020-06-19 13:39:01 +02:00
parent 062a999e85
commit 1b09b4f950
12 changed files with 89 additions and 2 deletions

View File

@ -180,7 +180,11 @@ appropriate ``PUSHi`` instruction. In the following example,
``3`` and ``2`` are added resulting in 5 and then the
bitwise ``and`` with the string "abc" is computed.
The final value is assigned to a local variable called ``x``.
Strings are stored left-aligned and cannot be longer than 32 bytes.
The limit does not apply to string literals passed to builtin functions that require
literal arguments (e.g. ``setimmutable`` or ``loadimmutable``). Those strings never end up in the
generated bytecode.
.. code-block:: yul

View File

@ -301,10 +301,15 @@ vector<YulString> AsmAnalyzer::operator()(FunctionCall const& _funCall)
for (size_t i = _funCall.arguments.size(); i > 0; i--)
{
Expression const& arg = _funCall.arguments[i - 1];
bool isLiteralArgument = needsLiteralArguments && (*needsLiteralArguments)[i - 1];
bool isStringLiteral = holds_alternative<Literal>(arg) && get<Literal>(arg).kind == LiteralKind::String;
if (isLiteralArgument && isStringLiteral)
argTypes.emplace_back(expectUnlimitedStringLiteral(get<Literal>(arg)));
else
argTypes.emplace_back(expectExpression(arg));
if (needsLiteralArguments && (*needsLiteralArguments)[i - 1])
if (isLiteralArgument)
{
if (!holds_alternative<Literal>(arg))
m_errorReporter.typeError(
@ -433,6 +438,14 @@ YulString AsmAnalyzer::expectExpression(Expression const& _expr)
return types.empty() ? m_dialect.defaultType : types.front();
}
YulString AsmAnalyzer::expectUnlimitedStringLiteral(Literal const& _literal)
{
yulAssert(_literal.kind == LiteralKind::String, "");
yulAssert(m_dialect.validTypeForLiteral(LiteralKind::String, _literal.value, _literal.type), "");
return {_literal.type};
}
void AsmAnalyzer::expectBoolExpression(Expression const& _expr)
{
YulString type = expectExpression(_expr);

View File

@ -97,6 +97,7 @@ 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.
YulString expectExpression(Expression const& _expr);
YulString expectUnlimitedStringLiteral(Literal const& _literal);
/// Vists the expression and expects it to return a single boolean value.
/// Reports an error otherwise.
void expectBoolExpression(Expression const& _expr);

View File

@ -0,0 +1,4 @@
contract C {
uint immutable long___name___that___definitely___exceeds___the___thirty___two___byte___limit = 0;
}
// ----

View File

@ -0,0 +1,17 @@
object "a" {
code {
setimmutable(
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
0x1234567890123456789012345678901234567890
)
}
}
// ----
// Assembly:
// /* "source":152:194 */
// 0x1234567890123456789012345678901234567890
// /* "source":32:204 */
// assignImmutable("0x85a5b1db611c82c46f5fa18e39ae218397536256c451e5de155a86de843a9ad6")
// Bytecode: 73123456789012345678901234567890123456789050
// Opcodes: PUSH20 0x1234567890123456789012345678901234567890 POP
// SourceMappings: 152:42:0:-:0;32:172

View File

@ -0,0 +1,6 @@
{
let x := byte(31, "11112222333344445555666677778888")
}
// ====
// dialect: evm
// ----

View File

@ -0,0 +1,6 @@
{
let addr := loadimmutable("address")
}
// ====
// dialect: evm
// ----

View File

@ -0,0 +1,7 @@
{
setimmutable(loadimmutable("abc"), "abc")
}
// ====
// dialect: evm
// ----
// TypeError 9114: (6-18): Function expects direct literals as arguments.

View File

@ -0,0 +1,6 @@
{
setimmutable("address", 0x1234567890123456789012345678901234567890)
}
// ====
// dialect: evm
// ----

View File

@ -0,0 +1,7 @@
{
let name := "long___name___that___definitely___exceeds___the___thirty___two___byte___limit"
}
// ====
// dialect: evm
// ----
// TypeError 3069: (18-97): String literal too long (77 > 32)

View File

@ -0,0 +1,7 @@
{
let x := byte(40, "long___value__that___definitely___exceeds___the___thirty___two___byte___limit")
}
// ====
// dialect: evm
// ----
// TypeError 3069: (24-103): String literal too long (77 > 32)

View File

@ -0,0 +1,9 @@
{
setimmutable(
"long___name___that___definitely___exceeds___the___thirty___two___byte___limit",
0x1234567890123456789012345678901234567890
)
}
// ====
// dialect: evm
// ----