mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #7091 from ethereum/isoltest-value-format-fix
[isoltest] Fix (aligned) hex parsing and formatting
This commit is contained in:
		
						commit
						d44f680a51
					
				| @ -101,7 +101,7 @@ contract C { | ||||
| // g1() -> FAILURE | ||||
| // h(uint256,uint256): 1, -2 -> 3 | ||||
| // j(bool): true -> false | ||||
| // k(bytes32): 0x10 -> 0x10, 0x10 | ||||
| // k(bytes32): 0x10001 -> 0x10001, 0x10001 | ||||
| // l(): hex"4200efef" -> 8 | ||||
| // m(bytes): 32, 32, 0x20 -> 32, 32, 0x20 | ||||
| // m(bytes): 32, 3, hex"AB33BB" -> 32, 3, left(0xAB33BB) | ||||
|  | ||||
| @ -21,6 +21,8 @@ | ||||
| 
 | ||||
| #include <liblangutil/Common.h> | ||||
| 
 | ||||
| #include <libdevcore/StringUtils.h> | ||||
| 
 | ||||
| #include <boost/algorithm/string.hpp> | ||||
| 
 | ||||
| #include <fstream> | ||||
| @ -96,10 +98,7 @@ bytes BytesUtils::convertHexNumber(string const& _literal) | ||||
| { | ||||
| 	try | ||||
| 	{ | ||||
| 		if (_literal.size() % 2) | ||||
| 			throw Error(Error::Type::ParserError, "Hex number encoding invalid."); | ||||
| 		else | ||||
| 			return fromHex(_literal); | ||||
| 		return fromHex(_literal); | ||||
| 	} | ||||
| 	catch (std::exception const&) | ||||
| 	{ | ||||
| @ -159,13 +158,10 @@ string BytesUtils::formatBoolean(bytes const& _bytes) | ||||
| 
 | ||||
| string BytesUtils::formatHex(bytes const& _bytes) | ||||
| { | ||||
| 	stringstream os; | ||||
| 	soltestAssert(!_bytes.empty() && _bytes.size() <= 32, ""); | ||||
| 	u256 value = fromBigEndian<u256>(_bytes); | ||||
| 
 | ||||
| 	string hex{toHex(_bytes, HexPrefix::Add)}; | ||||
| 	boost::algorithm::replace_all(hex, "00", ""); | ||||
| 	os << hex; | ||||
| 
 | ||||
| 	return os.str(); | ||||
| 	return toCompactHexWithPrefix(value); | ||||
| } | ||||
| 
 | ||||
| string BytesUtils::formatHexString(bytes const& _bytes) | ||||
|  | ||||
| @ -252,104 +252,97 @@ Parameter TestFileParser::parseParameter() | ||||
| 		parameter.alignment = Parameter::Alignment::Right; | ||||
| 	} | ||||
| 
 | ||||
| 	try | ||||
| 	if (accept(Token::Sub, true)) | ||||
| 	{ | ||||
| 		if (accept(Token::Sub, true)) | ||||
| 		{ | ||||
| 			parameter.rawString += formatToken(Token::Sub); | ||||
| 			isSigned = true; | ||||
| 		} | ||||
| 		if (accept(Token::Boolean)) | ||||
| 		{ | ||||
| 			if (isSigned) | ||||
| 				throw Error(Error::Type::ParserError, "Invalid boolean literal."); | ||||
| 
 | ||||
| 			parameter.abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32}; | ||||
| 			string parsed = parseBoolean(); | ||||
| 			parameter.rawString += parsed; | ||||
| 			parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 				parameter.alignment, | ||||
| 				parameter.abiType, | ||||
| 				BytesUtils::convertBoolean(parsed) | ||||
| 			); | ||||
| 		} | ||||
| 		else if (accept(Token::HexNumber)) | ||||
| 		{ | ||||
| 			if (isSigned) | ||||
| 				throw Error(Error::Type::ParserError, "Invalid hex number literal."); | ||||
| 
 | ||||
| 			parameter.abiType = ABIType{ABIType::Hex, ABIType::AlignRight, 32}; | ||||
| 			string parsed = parseHexNumber(); | ||||
| 			parameter.rawString += parsed; | ||||
| 			parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 				parameter.alignment, | ||||
| 				parameter.abiType, | ||||
| 				BytesUtils::convertHexNumber(parsed) | ||||
| 			); | ||||
| 		} | ||||
| 		else if (accept(Token::Hex, true)) | ||||
| 		{ | ||||
| 			if (isSigned) | ||||
| 				throw Error(Error::Type::ParserError, "Invalid hex string literal."); | ||||
| 			if (parameter.alignment != Parameter::Alignment::None) | ||||
| 				throw Error(Error::Type::ParserError, "Hex string literals cannot be aligned or padded."); | ||||
| 
 | ||||
| 			string parsed = parseString(); | ||||
| 			parameter.rawString += "hex\"" + parsed + "\""; | ||||
| 			parameter.rawBytes = BytesUtils::convertHexNumber(parsed); | ||||
| 			parameter.abiType = ABIType{ | ||||
| 				ABIType::HexString, ABIType::AlignNone, parameter.rawBytes.size() | ||||
| 			}; | ||||
| 		} | ||||
| 		else if (accept(Token::String)) | ||||
| 		{ | ||||
| 			if (isSigned) | ||||
| 				throw Error(Error::Type::ParserError, "Invalid string literal."); | ||||
| 			if (parameter.alignment != Parameter::Alignment::None) | ||||
| 				throw Error(Error::Type::ParserError, "String literals cannot be aligned or padded."); | ||||
| 
 | ||||
| 			string parsed = parseString(); | ||||
| 			parameter.abiType = ABIType{ABIType::String, ABIType::AlignLeft, parsed.size()}; | ||||
| 			parameter.rawString += "\"" + parsed + "\""; | ||||
| 			parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 				Parameter::Alignment::Left, | ||||
| 				parameter.abiType, | ||||
| 				BytesUtils::convertString(parsed) | ||||
| 			); | ||||
| 		} | ||||
| 		else if (accept(Token::Number)) | ||||
| 		{ | ||||
| 			auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec; | ||||
| 
 | ||||
| 			parameter.abiType = ABIType{type, ABIType::AlignRight, 32}; | ||||
| 			string parsed = parseDecimalNumber(); | ||||
| 			parameter.rawString += parsed; | ||||
| 			if (isSigned) | ||||
| 				parsed = "-" + parsed; | ||||
| 
 | ||||
| 			parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 				parameter.alignment, | ||||
| 				parameter.abiType, | ||||
| 				BytesUtils::convertNumber(parsed) | ||||
| 			); | ||||
| 		} | ||||
| 		else if (accept(Token::Failure, true)) | ||||
| 		{ | ||||
| 			if (isSigned) | ||||
| 				throw Error(Error::Type::ParserError, "Invalid failure literal."); | ||||
| 
 | ||||
| 			parameter.abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0}; | ||||
| 			parameter.rawBytes = bytes{}; | ||||
| 		} | ||||
| 		if (parameter.alignment != Parameter::Alignment::None) | ||||
| 		{ | ||||
| 			expect(Token::RParen); | ||||
| 			parameter.rawString += formatToken(Token::RParen); | ||||
| 		} | ||||
| 		parameter.rawString += formatToken(Token::Sub); | ||||
| 		isSigned = true; | ||||
| 	} | ||||
| 	catch (std::exception const&) | ||||
| 	if (accept(Token::Boolean)) | ||||
| 	{ | ||||
| 		throw Error(Error::Type::ParserError, "Literal encoding invalid."); | ||||
| 		if (isSigned) | ||||
| 			throw Error(Error::Type::ParserError, "Invalid boolean literal."); | ||||
| 
 | ||||
| 		parameter.abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32}; | ||||
| 		string parsed = parseBoolean(); | ||||
| 		parameter.rawString += parsed; | ||||
| 		parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 			parameter.alignment, | ||||
| 			parameter.abiType, | ||||
| 			BytesUtils::convertBoolean(parsed) | ||||
| 		); | ||||
| 	} | ||||
| 	else if (accept(Token::HexNumber)) | ||||
| 	{ | ||||
| 		if (isSigned) | ||||
| 			throw Error(Error::Type::ParserError, "Invalid hex number literal."); | ||||
| 
 | ||||
| 		parameter.abiType = ABIType{ABIType::Hex, ABIType::AlignRight, 32}; | ||||
| 		string parsed = parseHexNumber(); | ||||
| 		parameter.rawString += parsed; | ||||
| 		parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 			parameter.alignment, | ||||
| 			parameter.abiType, | ||||
| 			BytesUtils::convertHexNumber(parsed) | ||||
| 		); | ||||
| 	} | ||||
| 	else if (accept(Token::Hex, true)) | ||||
| 	{ | ||||
| 		if (isSigned) | ||||
| 			throw Error(Error::Type::ParserError, "Invalid hex string literal."); | ||||
| 		if (parameter.alignment != Parameter::Alignment::None) | ||||
| 			throw Error(Error::Type::ParserError, "Hex string literals cannot be aligned or padded."); | ||||
| 
 | ||||
| 		string parsed = parseString(); | ||||
| 		parameter.rawString += "hex\"" + parsed + "\""; | ||||
| 		parameter.rawBytes = BytesUtils::convertHexNumber(parsed); | ||||
| 		parameter.abiType = ABIType{ | ||||
| 			ABIType::HexString, ABIType::AlignNone, parameter.rawBytes.size() | ||||
| 		}; | ||||
| 	} | ||||
| 	else if (accept(Token::String)) | ||||
| 	{ | ||||
| 		if (isSigned) | ||||
| 			throw Error(Error::Type::ParserError, "Invalid string literal."); | ||||
| 		if (parameter.alignment != Parameter::Alignment::None) | ||||
| 			throw Error(Error::Type::ParserError, "String literals cannot be aligned or padded."); | ||||
| 
 | ||||
| 		string parsed = parseString(); | ||||
| 		parameter.abiType = ABIType{ABIType::String, ABIType::AlignLeft, parsed.size()}; | ||||
| 		parameter.rawString += "\"" + parsed + "\""; | ||||
| 		parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 			Parameter::Alignment::Left, | ||||
| 			parameter.abiType, | ||||
| 			BytesUtils::convertString(parsed) | ||||
| 		); | ||||
| 	} | ||||
| 	else if (accept(Token::Number)) | ||||
| 	{ | ||||
| 		auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec; | ||||
| 
 | ||||
| 		parameter.abiType = ABIType{type, ABIType::AlignRight, 32}; | ||||
| 		string parsed = parseDecimalNumber(); | ||||
| 		parameter.rawString += parsed; | ||||
| 		if (isSigned) | ||||
| 			parsed = "-" + parsed; | ||||
| 
 | ||||
| 		parameter.rawBytes = BytesUtils::applyAlign( | ||||
| 			parameter.alignment, | ||||
| 			parameter.abiType, | ||||
| 			BytesUtils::convertNumber(parsed) | ||||
| 		); | ||||
| 	} | ||||
| 	else if (accept(Token::Failure, true)) | ||||
| 	{ | ||||
| 		if (isSigned) | ||||
| 			throw Error(Error::Type::ParserError, "Invalid failure literal."); | ||||
| 
 | ||||
| 		parameter.abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0}; | ||||
| 		parameter.rawBytes = bytes{}; | ||||
| 	} | ||||
| 	if (parameter.alignment != Parameter::Alignment::None) | ||||
| 	{ | ||||
| 		expect(Token::RParen); | ||||
| 		parameter.rawString += formatToken(Token::RParen); | ||||
| 	} | ||||
| 
 | ||||
| 	return parameter; | ||||
|  | ||||
| @ -404,6 +404,27 @@ BOOST_AUTO_TEST_CASE(call_arguments_string) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(call_hex_number) | ||||
| { | ||||
| 	char const* source = R"( | ||||
| 		// f(bytes32, bytes32): 0x616, 0x1042 -> 1
 | ||||
| 	)"; | ||||
| 	auto const calls = parse(source); | ||||
| 	BOOST_REQUIRE_EQUAL(calls.size(), 1); | ||||
| 	testFunctionCall( | ||||
| 		calls.at(0), | ||||
| 		Mode::SingleLine, | ||||
| 		"f(bytes32,bytes32)", | ||||
| 		false, | ||||
| 		fmt::encodeArgs( | ||||
| 			fromHex("0x616"), | ||||
| 			fromHex("0x1042") | ||||
| 		), | ||||
| 		fmt::encodeArgs(1) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(call_return_string) | ||||
| { | ||||
| 	char const* source = R"( | ||||
| @ -786,14 +807,6 @@ BOOST_AUTO_TEST_CASE(call_ether_type_invalid) | ||||
| 	BOOST_REQUIRE_THROW(parse(source), langutil::Error); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(call_hex_number_invalid) | ||||
| { | ||||
| 	char const* source = R"( | ||||
| 		// f(bytes32, bytes32): 0x616, 0x042 -> 1
 | ||||
| 	)"; | ||||
| 	BOOST_REQUIRE_THROW(parse(source), langutil::Error); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(call_signed_bool_invalid) | ||||
| { | ||||
| 	char const* source = R"( | ||||
|  | ||||
| @ -193,7 +193,7 @@ string TestFunctionCall::formatBytesParameters( | ||||
| 		fill_n( | ||||
| 			back_inserter(defaultParameters), | ||||
| 			ceil(_bytes.size() / 32), | ||||
| 			Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}} | ||||
| 			Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}} | ||||
| 		); | ||||
| 		ContractABIUtils::overwriteParameters(_errorReporter, defaultParameters, _parameters); | ||||
| 		os << BytesUtils::formatBytesRange(_bytes, defaultParameters, _highlight); | ||||
|  | ||||
| @ -139,7 +139,8 @@ BOOST_AUTO_TEST_CASE(format_hex_singleline) | ||||
| 	BOOST_REQUIRE_EQUAL(test.format(), "// f(bytes32): 0x31 -> 0x31"); | ||||
| 
 | ||||
| 	bytes actualResult = fromHex("0x32"); | ||||
| 	bytes actualBytes = actualResult + bytes(32 - actualResult.size(), 0); | ||||
| 	bytes actualBytes = bytes(32 - actualResult.size(), 0) + actualResult; | ||||
| 
 | ||||
| 	test.setRawBytes(actualBytes); | ||||
| 	test.setFailure(false); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user