Skip to content

Commit 16bc15a

Browse files
author
Leo Alt
committed
Fix false negative on storage array references returned by internal functions
1 parent a3d8da2 commit 16bc15a

File tree

4 files changed

+47
-19
lines changed

4 files changed

+47
-19
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Compiler Features:
1313
Bugfixes:
1414
* SMTChecker: Fix false positive in external calls from constructors.
1515
* SMTChecker: Fix internal error on some multi-source uses of ``abi.*``, cryptographic functions and constants.
16+
* SMTChecker: Fix false negative caused by ``push`` on storage array references returned by internal functions.
1617

1718

1819

libsolidity/formal/SMTEncoder.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,26 +1977,32 @@ void SMTEncoder::assignment(
19771977
indexOrMemberAssignment(*left, _right);
19781978
else if (auto const* funCall = dynamic_cast<FunctionCall const*>(left))
19791979
{
1980-
if (
1981-
auto funType = dynamic_cast<FunctionType const*>(funCall->expression().annotation().type);
1982-
funType && funType->kind() == FunctionType::Kind::ArrayPush
1983-
)
1980+
if (auto funType = dynamic_cast<FunctionType const*>(funCall->expression().annotation().type))
19841981
{
1985-
auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression());
1986-
solAssert(memberAccess, "");
1987-
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
1988-
solAssert(symbArray, "");
1989-
1990-
auto oldLength = symbArray->length();
1991-
auto store = smtutil::Expression::store(
1992-
symbArray->elements(),
1993-
symbArray->length() - 1,
1994-
_right
1995-
);
1996-
symbArray->increaseIndex();
1997-
m_context.addAssertion(symbArray->elements() == store);
1998-
m_context.addAssertion(symbArray->length() == oldLength);
1999-
assignment(memberAccess->expression(), symbArray->currentValue());
1982+
if (funType->kind() == FunctionType::Kind::ArrayPush)
1983+
{
1984+
auto memberAccess = dynamic_cast<MemberAccess const*>(&funCall->expression());
1985+
solAssert(memberAccess, "");
1986+
auto symbArray = dynamic_pointer_cast<smt::SymbolicArrayVariable>(m_context.expression(memberAccess->expression()));
1987+
solAssert(symbArray, "");
1988+
1989+
auto oldLength = symbArray->length();
1990+
auto store = smtutil::Expression::store(
1991+
symbArray->elements(),
1992+
symbArray->length() - 1,
1993+
_right
1994+
);
1995+
symbArray->increaseIndex();
1996+
m_context.addAssertion(symbArray->elements() == store);
1997+
m_context.addAssertion(symbArray->length() == oldLength);
1998+
assignment(memberAccess->expression(), symbArray->currentValue());
1999+
}
2000+
else if (funType->kind() == FunctionType::Kind::Internal)
2001+
{
2002+
for (auto type: funType->returnParameterTypes())
2003+
if (type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type))
2004+
resetReferences(type);
2005+
}
20002006
}
20012007
}
20022008
else
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
contract C {
2+
bytes x;
3+
4+
function getX() internal view returns (bytes storage) {
5+
return x;
6+
}
7+
8+
function s() public {
9+
require(x.length == 0);
10+
getX().push("a");
11+
assert(x.length == 1); // should hold but knowledge is erased due to pushing a reference
12+
assert(x.length == 0); // should fail
13+
}
14+
}
15+
// ====
16+
// SMTEngine: all
17+
// SMTIgnoreCex: yes
18+
// ----
19+
// Warning 6328: (168-189): CHC: Assertion violation happens here.
20+
// Warning 6328: (259-280): CHC: Assertion violation happens here.

test/libsolidity/smtCheckerTests/array_members/storage_pointer_push_1.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ contract C {
1717
// SMTEngine: all
1818
// SMTIgnoreCex: yes
1919
// ----
20+
// Warning 6368: (159-169): CHC: Out of bounds access happens here.
2021
// Warning 6328: (152-181): CHC: Assertion violation happens here.

0 commit comments

Comments
 (0)