mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #10073 from ethereum/smt_format_array_cex
Format array cex
This commit is contained in:
		
						commit
						1f50b86aad
					
				| @ -211,11 +211,8 @@ private: | ||||
| 		for (unsigned i = 0; i < _values.size(); ++i) | ||||
| 		{ | ||||
| 			auto var = _variables.at(i); | ||||
| 			if (var && var->type()->isValueType()) | ||||
| 			{ | ||||
| 				solAssert(_values.at(i), ""); | ||||
| 			if (var && _values.at(i)) | ||||
| 				assignments.emplace_back(var->name() + " = " + *_values.at(i)); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		return boost::algorithm::join(assignments, _separator); | ||||
|  | ||||
| @ -174,11 +174,8 @@ string Predicate::formatSummaryCall(vector<smtutil::Expression> const& _args) co | ||||
| 	auto const& params = fun->parameters(); | ||||
| 	solAssert(params.size() == functionArgsCex.size(), ""); | ||||
| 	for (unsigned i = 0; i < params.size(); ++i) | ||||
| 		if (params[i]->type()->isValueType()) | ||||
| 		{ | ||||
| 			solAssert(functionArgsCex.at(i), ""); | ||||
| 		if (params.at(i) && functionArgsCex.at(i)) | ||||
| 			functionArgs.emplace_back(*functionArgsCex.at(i)); | ||||
| 		} | ||||
| 		else | ||||
| 			functionArgs.emplace_back(params[i]->name()); | ||||
| 
 | ||||
| @ -298,6 +295,76 @@ optional<string> Predicate::expressionToString(smtutil::Expression const& _expr, | ||||
| 		solAssert(_expr.arguments.empty(), ""); | ||||
| 		return _expr.name; | ||||
| 	} | ||||
| 	if (smt::isArray(*_type)) | ||||
| 	{ | ||||
| 		auto const& arrayType = dynamic_cast<ArrayType const&>(*_type); | ||||
| 		solAssert(_expr.name == "tuple_constructor", ""); | ||||
| 		auto const& tupleSort = dynamic_cast<TupleSort const&>(*_expr.sort); | ||||
| 		solAssert(tupleSort.components.size() == 2, ""); | ||||
| 
 | ||||
| 		auto length = stoul(_expr.arguments.at(1).name); | ||||
| 		// Limit this counterexample size to 1k.
 | ||||
| 		// Some OSs give you "unlimited" memory through swap and other virtual memory,
 | ||||
| 		// so purely relying on bad_alloc being thrown is not a good idea.
 | ||||
| 		// In that case, the array allocation might cause OOM and the program is killed.
 | ||||
| 		if (length >= 1024) | ||||
| 			return {}; | ||||
| 		try | ||||
| 		{ | ||||
| 			vector<string> array(length); | ||||
| 			if (!fillArray(_expr.arguments.at(0), array, arrayType)) | ||||
| 				return {}; | ||||
| 			return "[" + boost::algorithm::join(array, ", ") + "]"; | ||||
| 		} | ||||
| 		catch (bad_alloc const&) | ||||
| 		{ | ||||
| 			// Solver gave a concrete array but length is too large.
 | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return {}; | ||||
| } | ||||
| 
 | ||||
| bool Predicate::fillArray(smtutil::Expression const& _expr, vector<string>& _array, ArrayType const& _type) const | ||||
| { | ||||
| 	// Base case
 | ||||
| 	if (_expr.name == "const_array") | ||||
| 	{ | ||||
| 		auto length = _array.size(); | ||||
| 		optional<string> elemStr = expressionToString(_expr.arguments.at(1), _type.baseType()); | ||||
| 		if (!elemStr) | ||||
| 			return false; | ||||
| 		_array.clear(); | ||||
| 		_array.resize(length, *elemStr); | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	// Recursive case.
 | ||||
| 	if (_expr.name == "store") | ||||
| 	{ | ||||
| 		if (!fillArray(_expr.arguments.at(0), _array, _type)) | ||||
| 			return false; | ||||
| 		optional<string> indexStr = expressionToString(_expr.arguments.at(1), TypeProvider::uint256()); | ||||
| 		if (!indexStr) | ||||
| 			return false; | ||||
| 		// Sometimes the solver assigns huge lengths that are not related,
 | ||||
| 		// we should catch and ignore those.
 | ||||
| 		unsigned index; | ||||
| 		try | ||||
| 		{ | ||||
| 			index = stoul(*indexStr); | ||||
| 		} | ||||
| 		catch (out_of_range const&) | ||||
| 		{ | ||||
| 			return true; | ||||
| 		} | ||||
| 		optional<string> elemStr = expressionToString(_expr.arguments.at(2), _type.baseType()); | ||||
| 		if (!elemStr) | ||||
| 			return false; | ||||
| 		if (index < _array.size()) | ||||
| 			_array.at(index) = *elemStr; | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	solAssert(false, ""); | ||||
| } | ||||
|  | ||||
| @ -128,6 +128,12 @@ private: | ||||
| 	/// @returns a string representation of the SMT expression based on a Solidity type.
 | ||||
| 	std::optional<std::string> expressionToString(smtutil::Expression const& _expr, TypePointer _type) const; | ||||
| 
 | ||||
| 	/// Recursively fills _array from _expr.
 | ||||
| 	/// _expr should have the form `store(store(...(const_array(x_0), i_0, e_0), i_m, e_m), i_k, e_k)`.
 | ||||
| 	/// @returns true if the construction worked,
 | ||||
| 	/// and false if at least one element could not be built.
 | ||||
| 	bool fillArray(smtutil::Expression const& _expr, std::vector<std::string>& _array, ArrayType const& _type) const; | ||||
| 
 | ||||
| 	/// The actual SMT expression.
 | ||||
| 	smt::SymbolicFunctionVariable m_predicate; | ||||
| 
 | ||||
|  | ||||
| @ -7,9 +7,7 @@ contract C { | ||||
|     function f(bool b) public { | ||||
|         if (b) | ||||
|             s.x[2] |= 1; | ||||
|         assert(s.x[2] != 1); | ||||
| 		// Removed because of Spacer nondeterminism. | ||||
|         //assert(s.x[2] != 1); | ||||
|     } | ||||
| } | ||||
| // ---- | ||||
| // Warning 6328: (173-192): CHC: Assertion violation might happen here. | ||||
| // Warning 7812: (173-192): BMC: Assertion violation might happen here. | ||||
|  | ||||
| @ -17,7 +17,8 @@ contract C | ||||
| 		// Should not fail since knowledge is erased only for mapping (uint => uint). | ||||
| 		assert(severalMaps8[0][0] == 42); | ||||
| 		// Should not fail since singleMap == severalMaps3d[0][0] is not possible. | ||||
| 		assert(severalMaps3d[0][0][0] == 42); | ||||
| 		// Removed because of Spacer nondeterminism. | ||||
| 		//assert(severalMaps3d[0][0][0] == 42); | ||||
| 		// Should fail since singleMap == map is possible. | ||||
| 		assert(map[0] == 42); | ||||
| 	} | ||||
| @ -26,4 +27,4 @@ contract C | ||||
| 	} | ||||
| } | ||||
| // ---- | ||||
| // Warning 6328: (781-801): CHC: Assertion violation happens here. | ||||
| // Warning 6328: (830-850): CHC: Assertion violation happens here. | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user