Skip to content

Commit 3b4d9bb

Browse files
r0qscameel
andcommitted
Fix segmentation fault when assigning to a parenthesized non-tuple expression of a tuple type
Co-authored-by: Kamil Śliwak <kamil.sliwak@codepoets.it>
1 parent d116a34 commit 3b4d9bb

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Bugfixes:
1616
* SMTChecker: Fix internal error when using bitwise operators with an array element as argument.
1717
* Standard JSON Interface: Fix ICE when the optimizer is disabled and an empty/blank string is used for ``optimizerSteps`` sequence.
1818
* StaticAnalyzer: Only raise a compile time error for division and modulo by zero when it's between literals.
19+
* TypeChecker: Fix compiler crash when the left-hand side of an assignment was a parenthesized non-tuple expression of a tuple type.
1920
* Yul Optimizer: Fix the order of assignments generated by ``SSATransform`` being dependent on AST IDs, sometimes resulting in different (but equivalent) bytecode when unrelated files were added to the compilation pipeline.
2021

2122

libsolidity/analysis/TypeChecker.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
116116
TupleType const& lhsType = dynamic_cast<TupleType const&>(*type(_lhs));
117117
TupleExpression const* lhsResolved = dynamic_cast<TupleExpression const*>(resolveOuterUnaryTuples(&_lhs));
118118

119-
if (lhsType.components().size() != _rhs.components().size() || lhsResolved->components().size() != _rhs.components().size())
119+
solAssert(!lhsResolved || lhsResolved->components().size() == lhsType.components().size());
120+
if (lhsType.components().size() != _rhs.components().size())
120121
{
121122
solAssert(m_errorReporter.hasErrors(), "");
122123
return;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
contract C {
2+
uint[] public array;
3+
4+
function f() public {
5+
// (f()) is not a tuple expression, but its value is a tuple.
6+
(f()) = ();
7+
}
8+
9+
function g() public {
10+
// (revert()) is not a tuple expression, but its value is a tuple.
11+
(revert()) = ();
12+
}
13+
14+
function h() internal returns (uint, uint) {}
15+
16+
function i() public {
17+
// (h()) is not a tuple expression, but its value is a tuple (uint, uint).
18+
(h()) = (1, 1);
19+
}
20+
21+
function j() public returns (uint, uint) {
22+
// (j()) is not a tuple expression, but its value is a tuple (uint, uint).
23+
(j()) = (1, 1);
24+
}
25+
26+
function m() public {
27+
// (uint x, uint y) is a tuple expression, and its value is a tuple (uint, uint).
28+
(uint x, uint y) = (1, 1);
29+
}
30+
31+
function n() public {
32+
// ((array.push(), array.push())) is a tuple expression of a tuple expression, and its value is a tuple (pointer uint, pointer uint).
33+
((array.push(), array.push())) = (1, 1);
34+
}
35+
}
36+
// ----
37+
// TypeError 4247: (126-129): Expression has to be an lvalue.
38+
// TypeError 4247: (236-244): Expression has to be an lvalue.
39+
// TypeError 4247: (407-410): Expression has to be an lvalue.
40+
// TypeError 4247: (550-553): Expression has to be an lvalue.

0 commit comments

Comments
 (0)