Skip to content

Commit 5688b3e

Browse files
committed
SMTChecker: Fix encoding of arguments of cryptographic functions
For example, the function ecrecover expect an argument of type fixed bytes, but due to implicit conversion, you can also pass a string literal. We previously did not take this into account in the encoding into SMT, which could let to SMT expressions having wrong sorts.
1 parent ed71f94 commit 5688b3e

File tree

3 files changed

+15
-8
lines changed

3 files changed

+15
-8
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Bugfixes:
1212
* General: Fix internal compiler error when requesting IR AST outputs for interfaces and abstract contracts.
1313
* SMTChecker: Fix SMT logic error when initializing a fixed-sized-bytes array using string literals.
1414
* SMTChecker: Fix SMT logic error when translating invariants involving array store and select operations.
15+
* SMTChecker: Fix wrong encoding of string literals as arguments of cryptographic functions.
1516
* Standard JSON Interface: Fix ``generatedSources`` and ``sourceMap`` being generated internally even when not requested.
1617
* Yul: Fix internal compiler error when a code generation error should be reported instead.
1718

libsolidity/formal/SMTEncoder.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
851851
{
852852
auto const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
853853
auto kind = funType.kind();
854-
auto arg0 = expr(*_funCall.arguments().at(0));
854+
auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::bytesStorage());
855855
std::optional<smtutil::Expression> result;
856856
if (kind == FunctionType::Kind::KECCAK256)
857857
result = smtutil::Expression::select(state().cryptoFunction("keccak256"), arg0);
@@ -862,10 +862,10 @@ void SMTEncoder::visitCryptoFunction(FunctionCall const& _funCall)
862862
else if (kind == FunctionType::Kind::ECRecover)
863863
{
864864
auto e = state().cryptoFunction("ecrecover");
865-
auto arg0 = expr(*_funCall.arguments().at(0));
866-
auto arg1 = expr(*_funCall.arguments().at(1));
867-
auto arg2 = expr(*_funCall.arguments().at(2));
868-
auto arg3 = expr(*_funCall.arguments().at(3));
865+
auto arg0 = expr(*_funCall.arguments().at(0), TypeProvider::fixedBytes(32));
866+
auto arg1 = expr(*_funCall.arguments().at(1), TypeProvider::uint(8));
867+
auto arg2 = expr(*_funCall.arguments().at(2), TypeProvider::fixedBytes(32));
868+
auto arg3 = expr(*_funCall.arguments().at(3), TypeProvider::fixedBytes(32));
869869
auto inputSort = dynamic_cast<smtutil::ArraySort&>(*e.sort).domain;
870870
auto ecrecoverInput = smtutil::Expression::tuple_constructor(
871871
smtutil::Expression(std::make_shared<smtutil::SortSort>(inputSort), ""),

test/libsolidity/smtCheckerTests/crypto/crypto_functions_same_string_literal.sol

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,25 @@ contract C {
55
assert(k1 == k2);
66
}
77

8-
function c2() public pure {
8+
function c2() public pure {
99
bytes32 s1 = sha256("10");
1010
bytes32 s2 = sha256("10");
1111
assert(s1 == s2);
1212
}
1313

14-
function c3() public pure {
14+
function c3() public pure {
1515
bytes32 r1 = ripemd160("100");
1616
bytes32 r2 = ripemd160("100");
1717
assert(r1 == r2);
1818
}
19+
20+
function c4() public pure {
21+
address e1 = ecrecover("a", 1, "b", "c");
22+
address e2 = ecrecover("a", 1, "b", "c");
23+
assert(e1 == e2);
24+
}
1925
}
2026
// ====
2127
// SMTEngine: chc
2228
// ----
23-
// Info 1391: CHC: 3 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them.
29+
// Info 1391: CHC: 4 verification condition(s) proved safe! Enable the model checker option "show proved safe" to see all of them.

0 commit comments

Comments
 (0)