Skip to content

Commit 6c7e686

Browse files
authored
Merge pull request #14980 from ethereum/smt-int-sorts-compatibility
SMTChecker: Relax assertions regarding sort compatibility when creating expressions
2 parents ae9bcab + 0c831e0 commit 6c7e686

File tree

3 files changed

+37
-17
lines changed

3 files changed

+37
-17
lines changed

Diff for: Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Compiler Features:
77

88

99
Bugfixes:
10+
* SMTChecker: Fix internal error on mapping access caused by too strong requirements on sort compatibility of the index and mapping domain.
1011
* SMTChecker: Fix internal error when using bitwise operators with an array element as argument.
1112

1213

Diff for: libsmtutil/SolverInterface.h

+11-17
Original file line numberDiff line numberDiff line change
@@ -189,10 +189,7 @@ class Expression
189189

190190
static Expression ite(Expression _condition, Expression _trueValue, Expression _falseValue)
191191
{
192-
if (_trueValue.sort->kind == Kind::Int)
193-
smtAssert(_trueValue.sort->kind == _falseValue.sort->kind, "");
194-
else
195-
smtAssert(*_trueValue.sort == *_falseValue.sort, "");
192+
smtAssert(areCompatible(*_trueValue.sort, *_falseValue.sort));
196193
SortPointer sort = _trueValue.sort;
197194
return Expression("ite", std::vector<Expression>{
198195
std::move(_condition), std::move(_trueValue), std::move(_falseValue)
@@ -216,10 +213,7 @@ class Expression
216213
std::shared_ptr<ArraySort> arraySort = std::dynamic_pointer_cast<ArraySort>(_array.sort);
217214
smtAssert(arraySort, "");
218215
smtAssert(_index.sort, "");
219-
if (arraySort->domain->kind == Kind::Int)
220-
smtAssert(arraySort->domain->kind == _index.sort->kind, "");
221-
else
222-
smtAssert(*arraySort->domain == *_index.sort, "");
216+
smtAssert(areCompatible(*arraySort->domain, *_index.sort));
223217
return Expression(
224218
"select",
225219
std::vector<Expression>{std::move(_array), std::move(_index)},
@@ -235,11 +229,8 @@ class Expression
235229
smtAssert(arraySort, "");
236230
smtAssert(_index.sort, "");
237231
smtAssert(_element.sort, "");
238-
smtAssert(*arraySort->domain == *_index.sort, "");
239-
if (arraySort->domain->kind == Kind::Int)
240-
smtAssert(arraySort->range->kind == _element.sort->kind, "");
241-
else
242-
smtAssert(*arraySort->range == *_element.sort, "");
232+
smtAssert(areCompatible(*arraySort->domain, *_index.sort));
233+
smtAssert(areCompatible(*arraySort->range, *_element.sort));
243234
return Expression(
244235
"store",
245236
std::vector<Expression>{std::move(_array), std::move(_index), std::move(_element)},
@@ -254,10 +245,7 @@ class Expression
254245
auto arraySort = std::dynamic_pointer_cast<ArraySort>(sortSort->inner);
255246
smtAssert(sortSort && arraySort, "");
256247
smtAssert(_value.sort, "");
257-
if (arraySort->domain->kind == Kind::Int)
258-
smtAssert(arraySort->range->kind == _value.sort->kind, "");
259-
else
260-
smtAssert(*arraySort->range == *_value.sort, "");
248+
smtAssert(areCompatible(*arraySort->range, *_value.sort));
261249
return Expression(
262250
"const_array",
263251
std::vector<Expression>{std::move(_sort), std::move(_value)},
@@ -501,6 +489,12 @@ class Expression
501489
SortPointer sort;
502490

503491
private:
492+
/// Helper method for checking sort compatibility when creating expressions
493+
/// Signed and unsigned Int sorts are compatible even though they are not same
494+
static bool areCompatible(Sort const& s1, Sort const& s2)
495+
{
496+
return s1.kind == Kind::Int ? s1.kind == s2.kind : s1 == s2;
497+
}
504498
/// Manual constructors, should only be used by SolverInterface and this class itself.
505499
Expression(std::string _name, std::vector<Expression> _arguments, Kind _kind):
506500
Expression(std::move(_name), std::move(_arguments), std::make_shared<Sort>(_kind)) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-3.0
2+
3+
4+
// Regression for handling signedness, see issue #14792
5+
contract C {
6+
mapping(int => int) v1;
7+
mapping(int => uint) v2;
8+
mapping(uint => int) v3;
9+
mapping(uint => uint) v4;
10+
mapping(bytes12 => int) v5;
11+
uint[5] a1;
12+
int[5] a2;
13+
14+
function f() public {
15+
delete v1[0];
16+
delete v2[0];
17+
delete v3[0];
18+
delete v4[0];
19+
delete v5[0];
20+
delete a1[0];
21+
delete a2[0];
22+
}
23+
}
24+
// ----
25+
// Info 1391: CHC: 2 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them.

0 commit comments

Comments
 (0)