mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #7210 from ethereum/smt_fix_type_mismatch
[SMTChecker] Support StringLiteral type
This commit is contained in:
		
						commit
						ffe906129f
					
				| @ -14,6 +14,7 @@ Compiler Features: | ||||
|  * Standard JSON Interface: Compile only selected sources and contracts. | ||||
|  * Standard JSON Interface: Provide secondary error locations (e.g. the source position of other conflicting declarations). | ||||
|  * SMTChecker: Do not erase knowledge about storage pointers if another storage pointer is assigned. | ||||
|  * SMTChecker: Support string literal type. | ||||
|  * Standard JSON Interface: Provide AST even on errors if ``--error-recovery`` commandline switch or StandardCompiler `settings.parserErrorRecovery` is true. | ||||
|  * Yul Optimizer: Do not inline function if it would result in expressions being duplicated that are not cheap. | ||||
| 
 | ||||
| @ -29,6 +30,7 @@ Bugfixes: | ||||
|  * SMTChecker: Fix internal error when inlining a function that returns a tuple containing an unsupported type inside a branch. | ||||
|  * SMTChecker: Fix internal error when inlining functions that use state variables and belong to a different source. | ||||
|  * SMTChecker: Fix internal error when reporting counterexamples concerning state variables from different source files. | ||||
|  * SMTChecker: Fix SMT sort mismatch when using string literals. | ||||
|  * View/Pure Checker: Properly detect state variable access through base class. | ||||
|  * Yul analyzer: Check availability of data objects already in analysis phase. | ||||
|  * Yul Optimizer: Fix an issue where memory-accessing code was removed even though ``msize`` was used in the program. | ||||
|  | ||||
| @ -187,7 +187,7 @@ void SMTEncoder::endVisit(VariableDeclarationStatement const& _varDecl) | ||||
| 						declarations.at(i) && | ||||
| 						m_context.knownVariable(*declarations.at(i)) | ||||
| 					) | ||||
| 						assignment(*declarations.at(i), components.at(i)->currentValue()); | ||||
| 						assignment(*declarations.at(i), components.at(i)->currentValue(declarations.at(i)->type())); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @ -235,30 +235,43 @@ void SMTEncoder::endVisit(Assignment const& _assignment) | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		auto const& type = _assignment.annotation().type; | ||||
| 		vector<smt::Expression> rightArguments; | ||||
| 		if (_assignment.rightHandSide().annotation().type->category() == Type::Category::Tuple) | ||||
| 		{ | ||||
| 			auto symbTuple = dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_assignment.rightHandSide())); | ||||
| 			solAssert(symbTuple, ""); | ||||
| 			for (auto const& component: symbTuple->components()) | ||||
| 			auto symbTupleLeft = dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_assignment.leftHandSide())); | ||||
| 			solAssert(symbTupleLeft, ""); | ||||
| 			auto symbTupleRight = dynamic_pointer_cast<smt::SymbolicTupleVariable>(m_context.expression(_assignment.rightHandSide())); | ||||
| 			solAssert(symbTupleRight, ""); | ||||
| 
 | ||||
| 			auto const& leftComponents = symbTupleLeft->components(); | ||||
| 			auto const& rightComponents = symbTupleRight->components(); | ||||
| 			solAssert(leftComponents.size() == rightComponents.size(), ""); | ||||
| 
 | ||||
| 			for (unsigned i = 0; i < leftComponents.size(); ++i) | ||||
| 			{ | ||||
| 				auto const& left = leftComponents.at(i); | ||||
| 				auto const& right = rightComponents.at(i); | ||||
| 				/// Right hand side tuple component cannot be empty.
 | ||||
| 				solAssert(component, ""); | ||||
| 				rightArguments.push_back(component->currentValue()); | ||||
| 				solAssert(right, ""); | ||||
| 				if (left) | ||||
| 					rightArguments.push_back(right->currentValue(left->originalType())); | ||||
| 				else | ||||
| 					rightArguments.push_back(right->currentValue()); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			auto rightHandSide = compoundOps.count(op) ? | ||||
| 				compoundAssignment(_assignment) : | ||||
| 				expr(_assignment.rightHandSide()); | ||||
| 				expr(_assignment.rightHandSide(), type); | ||||
| 			defineExpr(_assignment, rightHandSide); | ||||
| 			rightArguments.push_back(expr(_assignment)); | ||||
| 			rightArguments.push_back(expr(_assignment, type)); | ||||
| 		} | ||||
| 		assignment( | ||||
| 			_assignment.leftHandSide(), | ||||
| 			rightArguments, | ||||
| 			_assignment.annotation().type, | ||||
| 			type, | ||||
| 			_assignment.location() | ||||
| 		); | ||||
| 	} | ||||
| @ -620,16 +633,10 @@ void SMTEncoder::endVisit(Literal const& _literal) | ||||
| 		defineExpr(_literal, smt::Expression(type.literalValue(&_literal))); | ||||
| 	else if (smt::isBool(type.category())) | ||||
| 		defineExpr(_literal, smt::Expression(_literal.token() == Token::TrueLiteral ? true : false)); | ||||
| 	else if (smt::isStringLiteral(type.category())) | ||||
| 		createExpr(_literal); | ||||
| 	else | ||||
| 	{ | ||||
| 		if (type.category() == Type::Category::StringLiteral) | ||||
| 		{ | ||||
| 			auto stringType = TypeProvider::stringMemory(); | ||||
| 			auto stringLit = dynamic_cast<StringLiteralType const*>(_literal.annotation().type); | ||||
| 			solAssert(stringLit, ""); | ||||
| 			auto result = smt::newSymbolicVariable(*stringType, stringLit->richIdentifier(), m_context); | ||||
| 			m_context.createExpression(_literal, result.second); | ||||
| 		} | ||||
| 		m_errorReporter.warning( | ||||
| 			_literal.location(), | ||||
| 			"Assertion checker does not yet support the type of this literal (" + | ||||
| @ -653,7 +660,7 @@ void SMTEncoder::endVisit(Return const& _return) | ||||
| 			for (unsigned i = 0; i < returnParams.size(); ++i) | ||||
| 			{ | ||||
| 				solAssert(components.at(i), ""); | ||||
| 				m_context.addAssertion(components.at(i)->currentValue() == m_context.newValue(*returnParams.at(i))); | ||||
| 				m_context.addAssertion(components.at(i)->currentValue(returnParams.at(i)->type()) == m_context.newValue(*returnParams.at(i))); | ||||
| 			} | ||||
| 		} | ||||
| 		else if (returnParams.size() == 1) | ||||
| @ -957,14 +964,15 @@ pair<smt::Expression, smt::Expression> SMTEncoder::arithmeticOperation( | ||||
| 
 | ||||
| void SMTEncoder::compareOperation(BinaryOperation const& _op) | ||||
| { | ||||
| 	solAssert(_op.annotation().commonType, ""); | ||||
| 	if (smt::isSupportedType(_op.annotation().commonType->category())) | ||||
| 	auto const& commonType = _op.annotation().commonType; | ||||
| 	solAssert(commonType, ""); | ||||
| 	if (smt::isSupportedType(commonType->category())) | ||||
| 	{ | ||||
| 		smt::Expression left(expr(_op.leftExpression())); | ||||
| 		smt::Expression right(expr(_op.rightExpression())); | ||||
| 		smt::Expression left(expr(_op.leftExpression(), commonType)); | ||||
| 		smt::Expression right(expr(_op.rightExpression(), commonType)); | ||||
| 		Token op = _op.getOperator(); | ||||
| 		shared_ptr<smt::Expression> value; | ||||
| 		if (smt::isNumber(_op.annotation().commonType->category())) | ||||
| 		if (smt::isNumber(commonType->category())) | ||||
| 		{ | ||||
| 			value = make_shared<smt::Expression>( | ||||
| 				op == Token::Equal ? (left == right) : | ||||
| @ -977,7 +985,7 @@ void SMTEncoder::compareOperation(BinaryOperation const& _op) | ||||
| 		} | ||||
| 		else // Bool
 | ||||
| 		{ | ||||
| 			solUnimplementedAssert(smt::isBool(_op.annotation().commonType->category()), "Operation not yet supported"); | ||||
| 			solUnimplementedAssert(smt::isBool(commonType->category()), "Operation not yet supported"); | ||||
| 			value = make_shared<smt::Expression>( | ||||
| 				op == Token::Equal ? (left == right) : | ||||
| 				/*op == Token::NotEqual*/ (left != right) | ||||
| @ -1104,7 +1112,7 @@ smt::Expression SMTEncoder::compoundAssignment(Assignment const& _assignment) | ||||
| 
 | ||||
| void SMTEncoder::assignment(VariableDeclaration const& _variable, Expression const& _value) | ||||
| { | ||||
| 	assignment(_variable, expr(_value)); | ||||
| 	assignment(_variable, expr(_value, _variable.type())); | ||||
| } | ||||
| 
 | ||||
| void SMTEncoder::assignment(VariableDeclaration const& _variable, smt::Expression const& _value) | ||||
| @ -1258,14 +1266,15 @@ bool SMTEncoder::createVariable(VariableDeclaration const& _varDecl) | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| smt::Expression SMTEncoder::expr(Expression const& _e) | ||||
| smt::Expression SMTEncoder::expr(Expression const& _e, TypePointer _targetType) | ||||
| { | ||||
| 	if (!m_context.knownExpression(_e)) | ||||
| 	{ | ||||
| 		m_errorReporter.warning(_e.location(), "Internal error: Expression undefined for SMT solver." ); | ||||
| 		createExpr(_e); | ||||
| 	} | ||||
| 	return m_context.expression(_e)->currentValue(); | ||||
| 
 | ||||
| 	return m_context.expression(_e)->currentValue(_targetType); | ||||
| } | ||||
| 
 | ||||
| void SMTEncoder::createExpr(Expression const& _e) | ||||
|  | ||||
| @ -175,8 +175,10 @@ protected: | ||||
| 	/// @returns an expression denoting the value of the variable declared in @a _decl
 | ||||
| 	/// at the given index. Does not ensure that this index exists.
 | ||||
| 	smt::Expression valueAtIndex(VariableDeclaration const& _decl, int _index); | ||||
| 	/// Returns the expression corresponding to the AST node. Throws if the expression does not exist.
 | ||||
| 	smt::Expression expr(Expression const& _e); | ||||
| 	/// Returns the expression corresponding to the AST node.
 | ||||
| 	/// If _targetType is not null apply conversion.
 | ||||
| 	/// Throws if the expression does not exist.
 | ||||
| 	smt::Expression expr(Expression const& _e, TypePointer _targetType = nullptr); | ||||
| 	/// Creates the expression (value can be arbitrary)
 | ||||
| 	void createExpr(Expression const& _e); | ||||
| 	/// Creates the expression and sets its value.
 | ||||
|  | ||||
| @ -64,6 +64,13 @@ SortPointer smtSort(solidity::Type const& _type) | ||||
| 			solAssert(mapType, ""); | ||||
| 			return make_shared<ArraySort>(smtSort(*mapType->keyType()), smtSort(*mapType->valueType())); | ||||
| 		} | ||||
| 		else if (isStringLiteral(_type.category())) | ||||
| 		{ | ||||
| 			auto stringLitType = dynamic_cast<solidity::StringLiteralType const*>(&_type); | ||||
| 			solAssert(stringLitType, ""); | ||||
| 			auto intSort = make_shared<Sort>(Kind::Int); | ||||
| 			return make_shared<ArraySort>(intSort, intSort); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			solAssert(isArray(_type.category()), ""); | ||||
| @ -127,19 +134,19 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable( | ||||
| 	if (!isSupportedTypeDeclaration(_type)) | ||||
| 	{ | ||||
| 		abstract = true; | ||||
| 		var = make_shared<SymbolicIntVariable>(solidity::TypeProvider::uint256(), _uniqueName, _context); | ||||
| 		var = make_shared<SymbolicIntVariable>(solidity::TypeProvider::uint256(), type, _uniqueName, _context); | ||||
| 	} | ||||
| 	else if (isBool(_type.category())) | ||||
| 		var = make_shared<SymbolicBoolVariable>(type, _uniqueName, _context); | ||||
| 	else if (isFunction(_type.category())) | ||||
| 		var = make_shared<SymbolicFunctionVariable>(type, _uniqueName, _context); | ||||
| 	else if (isInteger(_type.category())) | ||||
| 		var = make_shared<SymbolicIntVariable>(type, _uniqueName, _context); | ||||
| 		var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); | ||||
| 	else if (isFixedBytes(_type.category())) | ||||
| 	{ | ||||
| 		auto fixedBytesType = dynamic_cast<solidity::FixedBytesType const*>(type); | ||||
| 		solAssert(fixedBytesType, ""); | ||||
| 		var = make_shared<SymbolicFixedBytesVariable>(fixedBytesType->numBytes(), _uniqueName, _context); | ||||
| 		var = make_shared<SymbolicFixedBytesVariable>(type, fixedBytesType->numBytes(), _uniqueName, _context); | ||||
| 	} | ||||
| 	else if (isAddress(_type.category()) || isContract(_type.category())) | ||||
| 		var = make_shared<SymbolicAddressVariable>(_uniqueName, _context); | ||||
| @ -150,16 +157,21 @@ pair<bool, shared_ptr<SymbolicVariable>> newSymbolicVariable( | ||||
| 		auto rational = dynamic_cast<solidity::RationalNumberType const*>(&_type); | ||||
| 		solAssert(rational, ""); | ||||
| 		if (rational->isFractional()) | ||||
| 			var = make_shared<SymbolicIntVariable>(solidity::TypeProvider::uint256(), _uniqueName, _context); | ||||
| 			var = make_shared<SymbolicIntVariable>(solidity::TypeProvider::uint256(), type, _uniqueName, _context); | ||||
| 		else | ||||
| 			var = make_shared<SymbolicIntVariable>(type, _uniqueName, _context); | ||||
| 			var = make_shared<SymbolicIntVariable>(type, type, _uniqueName, _context); | ||||
| 	} | ||||
| 	else if (isMapping(_type.category())) | ||||
| 		var = make_shared<SymbolicMappingVariable>(type, _uniqueName, _context); | ||||
| 	else if (isArray(_type.category())) | ||||
| 		var = make_shared<SymbolicArrayVariable>(type, _uniqueName, _context); | ||||
| 		var = make_shared<SymbolicArrayVariable>(type, type, _uniqueName, _context); | ||||
| 	else if (isTuple(_type.category())) | ||||
| 		var = make_shared<SymbolicTupleVariable>(type, _uniqueName, _context); | ||||
| 	else if (isStringLiteral(_type.category())) | ||||
| 	{ | ||||
| 		auto stringType = TypeProvider::stringMemory(); | ||||
| 		var = make_shared<SymbolicArrayVariable>(stringType, type, _uniqueName, _context); | ||||
| 	} | ||||
| 	else | ||||
| 		solAssert(false, ""); | ||||
| 	return make_pair(abstract, var); | ||||
| @ -232,7 +244,8 @@ bool isMapping(solidity::Type::Category _category) | ||||
| 
 | ||||
| bool isArray(solidity::Type::Category _category) | ||||
| { | ||||
| 	return _category == solidity::Type::Category::Array; | ||||
| 	return _category == solidity::Type::Category::Array || | ||||
| 		_category == solidity::Type::Category::StringLiteral; | ||||
| } | ||||
| 
 | ||||
| bool isTuple(solidity::Type::Category _category) | ||||
| @ -240,6 +253,11 @@ bool isTuple(solidity::Type::Category _category) | ||||
| 	return _category == solidity::Type::Category::Tuple; | ||||
| } | ||||
| 
 | ||||
| bool isStringLiteral(solidity::Type::Category _category) | ||||
| { | ||||
| 	return _category == solidity::Type::Category::StringLiteral; | ||||
| } | ||||
| 
 | ||||
| Expression minValue(solidity::IntegerType const& _type) | ||||
| { | ||||
| 	return Expression(_type.minValue()); | ||||
|  | ||||
| @ -54,6 +54,7 @@ bool isFunction(solidity::Type::Category _category); | ||||
| bool isMapping(solidity::Type::Category _category); | ||||
| bool isArray(solidity::Type::Category _category); | ||||
| bool isTuple(solidity::Type::Category _category); | ||||
| bool isStringLiteral(solidity::Type::Category _category); | ||||
| 
 | ||||
| /// Returns a new symbolic variable, according to _type.
 | ||||
| /// Also returns whether the type is abstract or not,
 | ||||
|  | ||||
| @ -27,10 +27,12 @@ using namespace dev::solidity::smt; | ||||
| 
 | ||||
| SymbolicVariable::SymbolicVariable( | ||||
| 	solidity::TypePointer _type, | ||||
| 	solidity::TypePointer _originalType, | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	m_type(move(_type)), | ||||
| 	m_type(_type), | ||||
| 	m_originalType(_originalType), | ||||
| 	m_uniqueName(move(_uniqueName)), | ||||
| 	m_context(_context), | ||||
| 	m_ssa(make_unique<SSAVariable>()) | ||||
| @ -53,7 +55,7 @@ SymbolicVariable::SymbolicVariable( | ||||
| 	solAssert(m_sort, ""); | ||||
| } | ||||
| 
 | ||||
| Expression SymbolicVariable::currentValue() const | ||||
| Expression SymbolicVariable::currentValue(solidity::TypePointer const&) const | ||||
| { | ||||
| 	return valueAtIndex(m_ssa->index()); | ||||
| } | ||||
| @ -95,17 +97,18 @@ SymbolicBoolVariable::SymbolicBoolVariable( | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicVariable(move(_type), move(_uniqueName), _context) | ||||
| 	SymbolicVariable(_type, _type, move(_uniqueName), _context) | ||||
| { | ||||
| 	solAssert(m_type->category() == solidity::Type::Category::Bool, ""); | ||||
| } | ||||
| 
 | ||||
| SymbolicIntVariable::SymbolicIntVariable( | ||||
| 	solidity::TypePointer _type, | ||||
| 	solidity::TypePointer _originalType, | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicVariable(move(_type), move(_uniqueName), _context) | ||||
| 	SymbolicVariable(_type, _originalType, move(_uniqueName), _context) | ||||
| { | ||||
| 	solAssert(isNumber(m_type->category()), ""); | ||||
| } | ||||
| @ -114,16 +117,17 @@ SymbolicAddressVariable::SymbolicAddressVariable( | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicIntVariable(TypeProvider::uint(160), move(_uniqueName), _context) | ||||
| 	SymbolicIntVariable(TypeProvider::uint(160), TypeProvider::uint(160), move(_uniqueName), _context) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| SymbolicFixedBytesVariable::SymbolicFixedBytesVariable( | ||||
| 	solidity::TypePointer _originalType, | ||||
| 	unsigned _numBytes, | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicIntVariable(TypeProvider::uint(_numBytes * 8), move(_uniqueName), _context) | ||||
| 	SymbolicIntVariable(TypeProvider::uint(_numBytes * 8), _originalType, move(_uniqueName), _context) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| @ -132,7 +136,7 @@ SymbolicFunctionVariable::SymbolicFunctionVariable( | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicVariable(move(_type), move(_uniqueName), _context), | ||||
| 	SymbolicVariable(_type, _type, move(_uniqueName), _context), | ||||
| 	m_declaration(m_context.newVariable(currentName(), m_sort)) | ||||
| { | ||||
| 	solAssert(m_type->category() == solidity::Type::Category::Function, ""); | ||||
| @ -171,27 +175,41 @@ SymbolicMappingVariable::SymbolicMappingVariable( | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicVariable(move(_type), move(_uniqueName), _context) | ||||
| 	SymbolicVariable(_type, _type, move(_uniqueName), _context) | ||||
| { | ||||
| 	solAssert(isMapping(m_type->category()), ""); | ||||
| } | ||||
| 
 | ||||
| SymbolicArrayVariable::SymbolicArrayVariable( | ||||
| 	solidity::TypePointer _type, | ||||
| 	solidity::TypePointer _originalType, | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicVariable(move(_type), move(_uniqueName), _context) | ||||
| 	SymbolicVariable(_type, _originalType, move(_uniqueName), _context) | ||||
| { | ||||
| 	solAssert(isArray(m_type->category()), ""); | ||||
| } | ||||
| 
 | ||||
| Expression SymbolicArrayVariable::currentValue(solidity::TypePointer const& _targetType) const | ||||
| { | ||||
| 	if (_targetType) | ||||
| 		// StringLiterals are encoded as SMT arrays in the generic case,
 | ||||
| 		// but they can also be compared/assigned to fixed bytes, in which
 | ||||
| 		// case they'd need to be encoded as numbers.
 | ||||
| 		if (auto strType = dynamic_cast<StringLiteralType const*>(m_originalType)) | ||||
| 			if (_targetType->category() == solidity::Type::Category::FixedBytes) | ||||
| 				return smt::Expression(u256(toHex(asBytes(strType->value()), HexPrefix::Add))); | ||||
| 
 | ||||
| 	return SymbolicVariable::currentValue(_targetType); | ||||
| } | ||||
| 
 | ||||
| SymbolicEnumVariable::SymbolicEnumVariable( | ||||
| 	solidity::TypePointer _type, | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicVariable(move(_type), move(_uniqueName), _context) | ||||
| 	SymbolicVariable(_type, _type, move(_uniqueName), _context) | ||||
| { | ||||
| 	solAssert(isEnum(m_type->category()), ""); | ||||
| } | ||||
| @ -201,7 +219,7 @@ SymbolicTupleVariable::SymbolicTupleVariable( | ||||
| 	string _uniqueName, | ||||
| 	EncodingContext& _context | ||||
| ): | ||||
| 	SymbolicVariable(move(_type), move(_uniqueName), _context) | ||||
| 	SymbolicVariable(_type, _type, move(_uniqueName), _context) | ||||
| { | ||||
| 	solAssert(isTuple(m_type->category()), ""); | ||||
| } | ||||
|  | ||||
| @ -40,6 +40,7 @@ class SymbolicVariable | ||||
| public: | ||||
| 	SymbolicVariable( | ||||
| 		solidity::TypePointer _type, | ||||
| 		solidity::TypePointer _originalType, | ||||
| 		std::string _uniqueName, | ||||
| 		EncodingContext& _context | ||||
| 	); | ||||
| @ -51,7 +52,7 @@ public: | ||||
| 
 | ||||
| 	virtual ~SymbolicVariable() = default; | ||||
| 
 | ||||
| 	Expression currentValue() const; | ||||
| 	virtual Expression currentValue(solidity::TypePointer const& _targetType = TypePointer{}) const; | ||||
| 	std::string currentName() const; | ||||
| 	virtual Expression valueAtIndex(int _index) const; | ||||
| 	virtual std::string nameAtIndex(int _index) const; | ||||
| @ -67,6 +68,7 @@ public: | ||||
| 
 | ||||
| 	SortPointer const& sort() const { return m_sort; } | ||||
| 	solidity::TypePointer const& type() const { return m_type; } | ||||
| 	solidity::TypePointer const& originalType() const { return m_originalType; } | ||||
| 
 | ||||
| protected: | ||||
| 	std::string uniqueSymbol(unsigned _index) const; | ||||
| @ -75,6 +77,8 @@ protected: | ||||
| 	SortPointer m_sort; | ||||
| 	/// Solidity type, used for size and range in number types.
 | ||||
| 	solidity::TypePointer m_type; | ||||
| 	/// Solidity original type, used for type conversion if necessary.
 | ||||
| 	solidity::TypePointer m_originalType; | ||||
| 	std::string m_uniqueName; | ||||
| 	EncodingContext& m_context; | ||||
| 	std::unique_ptr<SSAVariable> m_ssa; | ||||
| @ -101,6 +105,7 @@ class SymbolicIntVariable: public SymbolicVariable | ||||
| public: | ||||
| 	SymbolicIntVariable( | ||||
| 		solidity::TypePointer _type, | ||||
| 		solidity::TypePointer _originalType, | ||||
| 		std::string _uniqueName, | ||||
| 		EncodingContext& _context | ||||
| 	); | ||||
| @ -125,6 +130,7 @@ class SymbolicFixedBytesVariable: public SymbolicIntVariable | ||||
| { | ||||
| public: | ||||
| 	SymbolicFixedBytesVariable( | ||||
| 		solidity::TypePointer _originalType, | ||||
| 		unsigned _numBytes, | ||||
| 		std::string _uniqueName, | ||||
| 		EncodingContext& _context | ||||
| @ -180,9 +186,12 @@ class SymbolicArrayVariable: public SymbolicVariable | ||||
| public: | ||||
| 	SymbolicArrayVariable( | ||||
| 		solidity::TypePointer _type, | ||||
| 		solidity::TypePointer _originalTtype, | ||||
| 		std::string _uniqueName, | ||||
| 		EncodingContext& _context | ||||
| 	); | ||||
| 
 | ||||
| 	Expression currentValue(solidity::TypePointer const& _targetType = TypePointer{}) const override; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | ||||
| @ -53,9 +53,6 @@ contract MyConc{ | ||||
| // ---- | ||||
| // Warning: (773-792): This declaration shadows an existing declaration. | ||||
| // Warning: (1009-1086): Function state mutability can be restricted to view | ||||
| // Warning: (327-332): Assertion checker does not yet support the type of this literal (literal_string "abc"). | ||||
| // Warning: (353-358): Assertion checker does not yet support the type of this literal (literal_string "xyz"). | ||||
| // Warning: (834-839): Assertion checker does not yet support the type of this literal (literal_string "abc"). | ||||
| // Warning: (874-879): Underflow (resulting value less than 0) happens here. | ||||
| // Warning: (874-879): Overflow (resulting value larger than 2**256 - 1) happens here. | ||||
| // Warning: (985-1002): Overflow (resulting value larger than 2**256 - 1) happens here. | ||||
|  | ||||
| @ -83,7 +83,6 @@ contract InternalCall { | ||||
| // Warning: (1144-1206): Function state mutability can be restricted to pure | ||||
| // Warning: (1212-1274): Function state mutability can be restricted to pure | ||||
| // Warning: (1280-1342): Function state mutability can be restricted to pure | ||||
| // Warning: (799-811): Assertion checker does not yet support the type of this literal (literal_string "helloTwo()"). | ||||
| // Warning: (782-813): Type conversion is not yet fully supported and might yield false positives. | ||||
| // Warning: (771-814): Assertion checker does not yet implement this type of function call. | ||||
| // Warning: (825-830): Assertion checker does not yet support the type of this variable. | ||||
|  | ||||
| @ -6,7 +6,5 @@ contract C { | ||||
| } | ||||
| // ---- | ||||
| // Warning: (31-64): Experimental features are turned on. Do not use experimental features on live deployments. | ||||
| // Warning: (173-175): Assertion checker does not yet support the type of this literal (literal_string ""). | ||||
| // Warning: (162-176): Assertion checker does not yet implement this type of function call. | ||||
| // Warning: (196-202): Assertion checker does not yet support the type of this literal (literal_string "7?8r"). | ||||
| // Warning: (178-203): Assertion checker does not yet implement this type of function call. | ||||
|  | ||||
| @ -8,4 +8,3 @@ contract C | ||||
| } | ||||
| // ---- | ||||
| // Warning: (76-91): Unused local variable. | ||||
| // Warning: (94-107): Assertion checker does not yet support the type of this literal (literal_string "Hello World"). | ||||
|  | ||||
| @ -0,0 +1,13 @@ | ||||
| pragma experimental SMTChecker; | ||||
| 
 | ||||
| contract C { | ||||
| 	function f(bytes32 _x) public pure { | ||||
| 		require(_x == "test"); | ||||
| 		bytes32 y = "test"; | ||||
| 		bytes16 z = "testz"; | ||||
| 		assert(_x == y); | ||||
| 		assert(_x == z); | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (175-190): Assertion violation happens here | ||||
| @ -0,0 +1,12 @@ | ||||
| pragma experimental SMTChecker; | ||||
| 
 | ||||
| contract C { | ||||
| 	function f(bytes32 _x) public pure { | ||||
| 		require(_x == "test"); | ||||
| 		(bytes32 y, bytes16 z) = ("test", "testz"); | ||||
| 		assert(_x == y); | ||||
| 		assert(_x == z); | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (176-191): Assertion violation happens here | ||||
| @ -0,0 +1,14 @@ | ||||
| pragma experimental SMTChecker; | ||||
| 
 | ||||
| contract C { | ||||
| 	function f(bytes32 _x) public pure { | ||||
| 		require(_x == "test"); | ||||
| 		bytes32 y; | ||||
| 		bytes16 z; | ||||
| 		(y, z) = ("test", "testz"); | ||||
| 		assert(_x == y); | ||||
| 		assert(_x == z); | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (186-201): Assertion violation happens here | ||||
| @ -0,0 +1,18 @@ | ||||
| pragma experimental SMTChecker; | ||||
| 
 | ||||
| contract C { | ||||
| 	function g() internal pure returns (bytes32, bytes16) { | ||||
| 		return ("test", "testz"); | ||||
| 	} | ||||
| 
 | ||||
| 	function f(bytes32 _x) public pure { | ||||
| 		require(_x == "test"); | ||||
| 		bytes32 y; | ||||
| 		bytes16 z; | ||||
| 		(y, z) = g(); | ||||
| 		assert(_x == y); | ||||
| 		assert(_x == z); | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (261-276): Assertion violation happens here | ||||
| @ -0,0 +1,16 @@ | ||||
| pragma experimental SMTChecker; | ||||
| 
 | ||||
| contract C { | ||||
| 	function g() internal pure returns (bytes32, bytes16) { | ||||
| 		return ("test", "testz"); | ||||
| 	} | ||||
| 
 | ||||
| 	function f(bytes32 _x) public pure { | ||||
| 		require(_x == "test"); | ||||
| 		(bytes32 y, bytes16 z) = g(); | ||||
| 		assert(_x == y); | ||||
| 		assert(_x == z); | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (251-266): Assertion violation happens here | ||||
| @ -0,0 +1,13 @@ | ||||
| pragma experimental SMTChecker; | ||||
| 
 | ||||
| contract C { | ||||
| 	function f(bytes32 _x) public pure { | ||||
| 		require(_x == "test"); | ||||
| 		bytes32 y = _x; | ||||
| 		bytes32 z = _x; | ||||
| 		assert(z == "test"); | ||||
| 		assert(y == "testx"); | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (170-190): Assertion violation happens here | ||||
| @ -0,0 +1,13 @@ | ||||
| pragma experimental SMTChecker; | ||||
| 
 | ||||
| contract C { | ||||
| 	function f(bytes32 _x) public pure { | ||||
| 		require(_x != "test"); | ||||
| 		bytes32 y = _x; | ||||
| 		bytes32 z = _x; | ||||
| 		assert(z == "test"); | ||||
| 		assert(y != "testx"); | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (147-166): Assertion violation happens here | ||||
| @ -6,4 +6,3 @@ contract C { | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning: (97-125): Assertion checker does not yet support the type of this literal (literal_string "Input number is too large."). | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user