aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/formal
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2019-01-21 19:35:07 +0800
committerGitHub <noreply@github.com>2019-01-21 19:35:07 +0800
commitf8e9aed839dce87cebb3e27f20ee8dbe4b782a84 (patch)
treebe766e5d6bd01d7dfd6966cdec9b0ec6b45b90de /libsolidity/formal
parentea790e3b7ed445ef632ea76958538c1d084001f0 (diff)
parenta10db051de404f9f049ad3a951c3b5a9de571697 (diff)
downloaddexon-solidity-f8e9aed839dce87cebb3e27f20ee8dbe4b782a84.tar.gz
dexon-solidity-f8e9aed839dce87cebb3e27f20ee8dbe4b782a84.tar.zst
dexon-solidity-f8e9aed839dce87cebb3e27f20ee8dbe4b782a84.zip
Merge pull request #5717 from ethereum/smt_typecast
[SMTChecker] Support basic typecast without truncation
Diffstat (limited to 'libsolidity/formal')
-rw-r--r--libsolidity/formal/SMTChecker.cpp45
-rw-r--r--libsolidity/formal/SMTChecker.h1
2 files changed, 45 insertions, 1 deletions
diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp
index 35c1e2f1..38715289 100644
--- a/libsolidity/formal/SMTChecker.cpp
+++ b/libsolidity/formal/SMTChecker.cpp
@@ -386,7 +386,7 @@ void SMTChecker::endVisit(BinaryOperation const& _op)
void SMTChecker::endVisit(FunctionCall const& _funCall)
{
solAssert(_funCall.annotation().kind != FunctionCallKind::Unset, "");
- if (_funCall.annotation().kind != FunctionCallKind::FunctionCall)
+ if (_funCall.annotation().kind == FunctionCallKind::StructConstructorCall)
{
m_errorReporter.warning(
_funCall.location(),
@@ -395,6 +395,12 @@ void SMTChecker::endVisit(FunctionCall const& _funCall)
return;
}
+ if (_funCall.annotation().kind == FunctionCallKind::TypeConversion)
+ {
+ visitTypeConversion(_funCall);
+ return;
+ }
+
FunctionType const& funType = dynamic_cast<FunctionType const&>(*_funCall.expression().annotation().type);
std::vector<ASTPointer<Expression const>> const args = _funCall.arguments();
@@ -571,6 +577,43 @@ void SMTChecker::endVisit(Identifier const& _identifier)
}
}
+void SMTChecker::visitTypeConversion(FunctionCall const& _funCall)
+{
+ solAssert(_funCall.annotation().kind == FunctionCallKind::TypeConversion, "");
+ solAssert(_funCall.arguments().size() == 1, "");
+ auto argument = _funCall.arguments().at(0);
+ unsigned argSize = argument->annotation().type->storageBytes();
+ unsigned castSize = _funCall.annotation().type->storageBytes();
+ if (argSize == castSize)
+ defineExpr(_funCall, expr(*argument));
+ else
+ {
+ createExpr(_funCall);
+ setUnknownValue(*m_expressions.at(&_funCall));
+ auto const& funCallCategory = _funCall.annotation().type->category();
+ // TODO: truncating and bytesX needs a different approach because of right padding.
+ if (funCallCategory == Type::Category::Integer || funCallCategory == Type::Category::Address)
+ {
+ if (argSize < castSize)
+ defineExpr(_funCall, expr(*argument));
+ else
+ {
+ auto const& intType = dynamic_cast<IntegerType const&>(*m_expressions.at(&_funCall)->type());
+ defineExpr(_funCall, smt::Expression::ite(
+ expr(*argument) >= minValue(intType) && expr(*argument) <= maxValue(intType),
+ expr(*argument),
+ expr(_funCall)
+ ));
+ }
+ }
+
+ m_errorReporter.warning(
+ _funCall.location(),
+ "Type conversion is not yet fully supported and might yield false positives."
+ );
+ }
+}
+
void SMTChecker::visitFunctionIdentifier(Identifier const& _identifier)
{
auto const& fType = dynamic_cast<FunctionType const&>(*_identifier.annotation().type);
diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h
index f14d2ac0..caa83764 100644
--- a/libsolidity/formal/SMTChecker.h
+++ b/libsolidity/formal/SMTChecker.h
@@ -86,6 +86,7 @@ private:
void visitAssert(FunctionCall const& _funCall);
void visitRequire(FunctionCall const& _funCall);
void visitGasLeft(FunctionCall const& _funCall);
+ void visitTypeConversion(FunctionCall const& _funCall);
/// Visits the FunctionDefinition of the called function
/// if available and inlines the return value.
void inlineFunctionCall(FunctionCall const& _funCall);