diff --git a/Changelog.md b/Changelog.md index f5de44491..e46caf9a2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,7 +12,7 @@ Compiler Features: Bugfixes: * Code Generator: Fix crash when passing an empty string literal to ``bytes.concat()``. * Code Generator: Fix internal compiler error when calling functions bound to calldata structs and arrays. - * Code Generator: Fix internal compiler error when passing zero to ``bytes.concat()``. + * Code Generator: Fix internal compiler error when passing a 32-byte hex literal or a zero literal to ``bytes.concat()`` by disallowing such literals. * Type Checker: Fix internal error and prevent static calls to unimplemented modifiers. diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 7bc1ff833..0c90d005c 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2033,11 +2033,14 @@ void TypeChecker::typeCheckBytesConcatFunction( typeCheckFunctionGeneralChecks(_functionCall, _functionType); for (shared_ptr<Expression const> const& argument: _functionCall.arguments()) - if ( - Type const* argumentType = type(*argument); + { + Type const* argumentType = type(*argument); + bool notConvertibleToBytes = !argumentType->isImplicitlyConvertibleTo(*TypeProvider::fixedBytes(32)) && - !argumentType->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()) - ) + !argumentType->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()); + bool numberLiteral = (dynamic_cast<RationalNumberType const*>(argumentType) != nullptr); + + if (notConvertibleToBytes || numberLiteral) m_errorReporter.typeError( 8015_error, argument->location(), @@ -2045,6 +2048,7 @@ void TypeChecker::typeCheckBytesConcatFunction( "bytes or fixed bytes type is required, but " + argumentType->toString(true) + " provided." ); + } } void TypeChecker::typeCheckFunctionGeneralChecks( diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index a8cb90d44..50a8fb6ca 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -593,7 +593,7 @@ public: private: rational m_value; - /// Bytes type to which the rational can be explicitly converted. + /// Bytes type to which the rational can be implicitly converted. /// Empty for all rationals that are not directly parsed from hex literals. Type const* m_compatibleBytesType; diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 89f9090a4..338430723 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1086,13 +1086,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) literalType && !literalType->value().empty() && literalType->value().size() <= 32 ) targetTypes.emplace_back(TypeProvider::fixedBytes(static_cast<unsigned>(literalType->value().size()))); - else if (auto const* literalType = dynamic_cast<RationalNumberType const*>(argument->annotation().type)) - { - solAssert(literalType->value() == 0, ""); - targetTypes.emplace_back(TypeProvider::fixedBytes(1)); - } else { + solAssert(!dynamic_cast<RationalNumberType const*>(argument->annotation().type), ""); solAssert(argument->annotation().type->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()), ""); targetTypes.emplace_back(TypeProvider::bytesMemory()); } diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index edc1c4ad2..d7c31a72b 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -2476,13 +2476,9 @@ string YulUtilFunctions::bytesConcatFunction(vector<Type const*> const& _argumen literalType && !literalType->value().empty() && literalType->value().size() <= 32 ) targetTypes.emplace_back(TypeProvider::fixedBytes(static_cast<unsigned>(literalType->value().size()))); - else if (auto const* literalType = dynamic_cast<RationalNumberType const*>(argumentType)) - { - solAssert(literalType->value() == 0, ""); - targetTypes.emplace_back(TypeProvider::fixedBytes(1)); - } else { + solAssert(!dynamic_cast<RationalNumberType const*>(argumentType), ""); solAssert(argumentType->isImplicitlyConvertibleTo(*TypeProvider::bytesMemory()), ""); targetTypes.emplace_back(TypeProvider::bytesMemory()); } diff --git a/test/libsolidity/semanticTests/array/concat/bytes_concat_zero.sol b/test/libsolidity/semanticTests/array/concat/bytes_concat_zero.sol deleted file mode 100644 index 602b39168..000000000 --- a/test/libsolidity/semanticTests/array/concat/bytes_concat_zero.sol +++ /dev/null @@ -1,15 +0,0 @@ -contract C { - function f() public returns (bytes memory) { - return bytes.concat(0, -0, 0.0, -0.0, 0e10, 0e-10, 0x00, (0)); - } - - function g() public returns (bytes memory) { - return bytes.concat(0, "abc", 0, "abc", 0); - } -} -// ==== -// compileViaYul: also -// compileToEwasm: also -// ---- -// f() -> 0x20, 8, "\0\0\0\0\0\0\0\0" -// g() -> 0x20, 9, "\0abc\0abc\0" diff --git a/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol b/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol index c6f63c161..f39e90396 100644 --- a/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol +++ b/test/libsolidity/syntaxTests/array/concat/bytes_concat_valid_type_literal.sol @@ -1,6 +1,13 @@ contract C { function f() public pure { - bytes.concat(0, -0, 0.0, -0.0, 0e10, 0e-10, (0), 0x00, hex"00", unicode"abc", "abc"); + bytes.concat( + hex"00", + hex"aabbcc", + unicode"abc", + "123", + "abc" + "123456789012345678901234567890123456789012345678901234567890" // Longer than 32 bytes + ); } } // ---- diff --git a/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_misc_literals_and_expressions.sol b/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_misc_literals_and_expressions.sol index 5c98a592f..bdc451966 100644 --- a/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_misc_literals_and_expressions.sol +++ b/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_misc_literals_and_expressions.sol @@ -12,9 +12,13 @@ contract C { 1e10, 1e-10, 0.1, + 0x1234567, 0x11112222333344445555666677778888999900, // One byte less than an address 0x1111222233334444555566667777888899990000, // Address 0x111122223333444455556666777788889999000011, // One byte more than an address + 0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff, // exactly 32 bytes + -0x0000000000000000000000000000000000000000000000000000000000000001, // exactly 32 bytes + bytes(bytes32(0x00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff))[:], f, (), (0, 0), @@ -28,21 +32,27 @@ contract C { } } // ---- -// TypeError 1227: (540-546): Index range access is only supported for dynamic calldata arrays. +// TypeError 9640: (697-779): Explicit type conversion not allowed from "bytes32" to "bytes memory". +// TypeError 1227: (697-782): Index range access is only supported for dynamic calldata arrays. +// TypeError 1227: (864-870): Index range access is only supported for dynamic calldata arrays. // TypeError 8015: (133-138): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but bool provided. // TypeError 8015: (152-153): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 1 provided. // TypeError 8015: (167-171): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 10000000000 provided. // TypeError 8015: (185-190): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but rational_const 1 / 10000000000 provided. // TypeError 8015: (204-207): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but rational_const 1 / 10 provided. -// TypeError 8015: (221-261): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 3806...(37 digits omitted)...1680 provided. -// TypeError 8015: (312-354): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but address provided. -// TypeError 8015: (381-425): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 2494...(42 digits omitted)...0497 provided. -// TypeError 8015: (472-473): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but function () provided. -// TypeError 8015: (487-489): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but tuple() provided. -// TypeError 8015: (503-509): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but tuple(int_const 0,int_const 0) provided. -// TypeError 8015: (523-526): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but uint8[1] provided. -// TypeError 8015: (540-546): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but uint8[1] slice provided. -// TypeError 8015: (560-566): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but uint8 provided. -// TypeError 8015: (580-587): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but contract C provided. -// TypeError 8015: (601-605): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but struct C.S provided. -// TypeError 8015: (619-622): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but enum C.E provided. +// TypeError 8015: (221-230): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 19088743 provided. +// TypeError 8015: (244-284): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 3806...(37 digits omitted)...1680 provided. +// TypeError 8015: (335-377): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but address provided. +// TypeError 8015: (404-448): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 2494...(42 digits omitted)...0497 provided. +// TypeError 8015: (495-561): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 3027...(66 digits omitted)...5855 provided. +// TypeError 8015: (596-663): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const -1 provided. +// TypeError 8015: (697-782): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but bytes slice provided. +// TypeError 8015: (796-797): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but function () provided. +// TypeError 8015: (811-813): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but tuple() provided. +// TypeError 8015: (827-833): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but tuple(int_const 0,int_const 0) provided. +// TypeError 8015: (847-850): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but uint8[1] provided. +// TypeError 8015: (864-870): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but uint8[1] slice provided. +// TypeError 8015: (884-890): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but uint8 provided. +// TypeError 8015: (904-911): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but contract C provided. +// TypeError 8015: (925-929): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but struct C.S provided. +// TypeError 8015: (943-946): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but enum C.E provided. diff --git a/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_zero_literal.sol b/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_zero_literal.sol new file mode 100644 index 000000000..e62d13add --- /dev/null +++ b/test/libsolidity/syntaxTests/array/concat/bytes_concat_wrong_type_zero_literal.sol @@ -0,0 +1,33 @@ +contract C { + function f() public pure { + bytes.concat( + 0, + -0, + 0.0, + -0.0, + 0e10, + -0e10, + 0e-10, + -0e-10, + (0), + 0x00, + -0x00, + 0x0000000000000000000000000000000000000000000000000000000000000000, // exactly 32 bytes + -0x0000000000000000000000000000000000000000000000000000000000000000 // exactly 32 bytes + ); + } +} +// ---- +// TypeError 8015: (78-79): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (93-95): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (109-112): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (126-130): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (144-148): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (162-167): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (181-186): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (200-206): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (220-223): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (237-241): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (255-260): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (274-340): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided. +// TypeError 8015: (374-441): Invalid type for argument in the bytes.concat function call. bytes or fixed bytes type is required, but int_const 0 provided.