Skip to content

Commit 19ad8b1

Browse files
Merge pull request #13279 from timweri/nested-tuple-oor-fix
2 parents 14488e3 + a9e03f5 commit 19ad8b1

File tree

4 files changed

+48
-4
lines changed

4 files changed

+48
-4
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Bugfixes:
1414
* Commandline Interface: Disallow the following options outside of the compiler mode: ``--via-ir``,``--metadata-literal``, ``--metadata-hash``, ``--model-checker-show-unproved``, ``--model-checker-div-mod-no-slacks``, ``--model-checker-engine``, ``--model-checker-invariants``, ``--model-checker-solvers``, ``--model-checker-timeout``, ``--model-checker-contracts``, ``--model-checker-targets``.
1515
* Type Checker: Fix null dereference in `abi.encodeCall` type checking of free function.
1616
* Type Checker: Fix compiler crash when `abi.encodeCall` received a tuple expression instead of an inline tuple.
17+
* Type Checker: Fix compiler crash on tuple assignments involving certain patterns with unary tuples on the left-hand side.
1718

1819

1920
### 0.8.15 (2022-06-15)

libsolidity/analysis/TypeChecker.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,9 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
112112
size_t storageByteAccesses = 0;
113113
auto count = [&](TupleExpression const& _lhs, TupleType const& _rhs, auto _recurse) -> void {
114114
TupleType const& lhsType = dynamic_cast<TupleType const&>(*type(_lhs));
115+
TupleExpression const* lhsResolved = dynamic_cast<TupleExpression const*>(resolveOuterUnaryTuples(&_lhs));
115116

116-
if (lhsType.components().size() != _rhs.components().size())
117+
if (lhsType.components().size() != _rhs.components().size() || lhsResolved->components().size() != _rhs.components().size())
117118
{
118119
solAssert(m_errorReporter.hasErrors(), "");
119120
return;
@@ -134,7 +135,7 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
134135
{
135136
if (bytesType && bytesType->numBytes() == 1)
136137
{
137-
if (FunctionCall const* lhsCall = dynamic_cast<FunctionCall const*>(resolveOuterUnaryTuples(_lhs.components().at(index).get())))
138+
if (FunctionCall const* lhsCall = dynamic_cast<FunctionCall const*>(resolveOuterUnaryTuples(lhsResolved->components().at(index).get())))
138139
{
139140
FunctionType const& callType = dynamic_cast<FunctionType const&>(*type(lhsCall->expression()));
140141
if (callType.kind() == FunctionType::Kind::ArrayPush)
@@ -147,7 +148,7 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
147148
}
148149
}
149150
}
150-
else if (IndexAccess const* indexAccess = dynamic_cast<IndexAccess const*>(resolveOuterUnaryTuples(_lhs.components().at(index).get())))
151+
else if (IndexAccess const* indexAccess = dynamic_cast<IndexAccess const*>(resolveOuterUnaryTuples(lhsResolved->components().at(index).get())))
151152
{
152153
if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(type(indexAccess->baseExpression())))
153154
if (arrayType->isByteArray() && arrayType->dataStoredIn(DataLocation::Storage))
@@ -156,7 +157,7 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
156157
}
157158
}
158159
else if (TupleType const* tupleType = dynamic_cast<TupleType const*>(componentType))
159-
if (auto const* lhsNested = dynamic_cast<TupleExpression const*>(_lhs.components().at(index).get()))
160+
if (auto const* lhsNested = dynamic_cast<TupleExpression const*>(lhsResolved->components().at(index).get()))
160161
if (auto const* rhsNestedType = dynamic_cast<TupleType const*>(_rhs.components().at(index)))
161162
_recurse(
162163
*lhsNested,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
function f() pure {
2+
((, ())) = (1, 3);
3+
}
4+
5+
function g() pure {
6+
((, ((, ())))) = (1, 3);
7+
}
8+
9+
function t() pure returns (int, int) {
10+
return (4, 5);
11+
}
12+
13+
function h() pure {
14+
((, ())) = t();
15+
}
16+
17+
function ff() pure {
18+
((((, ())) , )) = ((1, 2), 3);
19+
}
20+
21+
function fg() pure {
22+
(((, ())) , ) = ((1, 2), 3);
23+
}
24+
25+
// ----
26+
// TypeError 5547: (28-30): Empty tuple on the left hand side.
27+
// TypeError 7407: (35-41): Type tuple(int_const 1,int_const 3) is not implicitly convertible to expected type tuple(,tuple()).
28+
// TypeError 5547: (78-80): Empty tuple on the left hand side.
29+
// TypeError 7407: (87-93): Type tuple(int_const 1,int_const 3) is not implicitly convertible to expected type tuple(,tuple(,tuple())).
30+
// TypeError 5547: (187-189): Empty tuple on the left hand side.
31+
// TypeError 7407: (194-197): Type tuple(int256,int256) is not implicitly convertible to expected type tuple(,tuple()).
32+
// TypeError 5547: (233-235): Empty tuple on the left hand side.
33+
// TypeError 7407: (245-256): Type tuple(tuple(int_const 1,int_const 2),int_const 3) is not implicitly convertible to expected type tuple(tuple(,tuple()),).
34+
// TypeError 5547: (291-293): Empty tuple on the left hand side.
35+
// TypeError 7407: (302-313): Type tuple(tuple(int_const 1,int_const 2),int_const 3) is not implicitly convertible to expected type tuple(tuple(,tuple()),).
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
contract A {
2+
function f() pure public {
3+
bytes1 b;
4+
bytes1 a;
5+
(((, , b))) = (1, 2, a);
6+
}
7+
}

0 commit comments

Comments
 (0)