aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md2
-rw-r--r--libsolidity/analysis/TypeChecker.cpp11
-rw-r--r--libsolidity/ast/Types.cpp2
-rw-r--r--libsolidity/ast/Types.h11
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp1
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp25
-rw-r--r--test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol11
-rw-r--r--test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol13
-rw-r--r--test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol13
-rw-r--r--test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol16
-rw-r--r--test/libsolidity/syntaxTests/specialFunctions/types_without_encoding_problems.sol9
11 files changed, 110 insertions, 4 deletions
diff --git a/Changelog.md b/Changelog.md
index a20a9a98..af09f804 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -10,11 +10,13 @@ Bugfixes:
* Code Generator: Do not include internal functions in the runtime bytecode which are only referenced in the constructor.
* Code Generator: Properly skip unneeded storage array cleanup when not reducing length.
* Code Generator: Bugfix in modifier lookup in libraries.
+ * Code Generator: Implement packed encoding of external function types.
* Commandline interface: Support ``--evm-version constantinople`` properly.
* DocString Parser: Fix error message for empty descriptions.
* Standard JSON: Support ``constantinople`` as ``evmVersion`` properly.
* Type System: Improve error message when attempting to shift by a fractional amount.
* Type System: Make external library functions accessible.
+ * Type System: Prevent encoding of weird types.
### 0.4.21 (2018-03-07)
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 6e287f83..620dfca4 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -1644,9 +1644,20 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
auto const& argType = type(*arguments[i]);
if (functionType->takesArbitraryParameters())
{
+ bool errored = false;
if (auto t = dynamic_cast<RationalNumberType const*>(argType.get()))
if (!t->mobileType())
+ {
m_errorReporter.typeError(arguments[i]->location(), "Invalid rational number (too large or division by zero).");
+ errored = true;
+ }
+ if (!errored && !(
+ argType->mobileType() &&
+ argType->mobileType()->interfaceType(false) &&
+ argType->mobileType()->interfaceType(false)->encodingType() &&
+ !(dynamic_cast<StructType const*>(argType->mobileType()->interfaceType(false)->encodingType().get()))
+ ))
+ m_errorReporter.typeError(arguments[i]->location(), "This type cannot be encoded.");
}
else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
m_errorReporter.typeError(
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 720215c9..4c462d09 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -1262,6 +1262,8 @@ bool ContractType::isPayable() const
TypePointer ContractType::unaryOperatorResult(Token::Value _operator) const
{
+ if (isSuper())
+ return TypePointer{};
return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer();
}
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index c930dd24..b7e64891 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -692,22 +692,27 @@ public:
virtual bool operator==(Type const& _other) const override;
virtual unsigned calldataEncodedSize(bool _padded ) const override
{
+ solAssert(!isSuper(), "");
return encodingType()->calldataEncodedSize(_padded);
}
- virtual unsigned storageBytes() const override { return 20; }
- virtual bool canLiveOutsideStorage() const override { return true; }
+ virtual unsigned storageBytes() const override { solAssert(!isSuper(), ""); return 20; }
+ virtual bool canLiveOutsideStorage() const override { return !isSuper(); }
virtual unsigned sizeOnStack() const override { return m_super ? 0 : 1; }
- virtual bool isValueType() const override { return true; }
+ virtual bool isValueType() const override { return !isSuper(); }
virtual std::string toString(bool _short) const override;
virtual std::string canonicalName() const override;
virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
virtual TypePointer encodingType() const override
{
+ if (isSuper())
+ return TypePointer{};
return std::make_shared<IntegerType>(160, IntegerType::Modifier::Address);
}
virtual TypePointer interfaceType(bool _inLibrary) const override
{
+ if (isSuper())
+ return TypePointer{};
return _inLibrary ? shared_from_this() : encodingType();
}
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index 68f0b3a1..676d5d4e 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -142,7 +142,6 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
dynamic_cast<FunctionType const&>(_type).kind() == FunctionType::Kind::External
)
{
- solUnimplementedAssert(_padToWordBoundaries, "Non-padded store for function not implemented.");
combineExternalFunctionType(true);
m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index a866e46c..f5813aed 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -2077,6 +2077,31 @@ BOOST_AUTO_TEST_CASE(packed_keccak256)
testContractAgainstCpp("a(bytes32)", f, u256(-1));
}
+BOOST_AUTO_TEST_CASE(packed_keccak256_complex_types)
+{
+ char const* sourceCode = R"(
+ contract test {
+ uint120[3] x;
+ function f() view returns (bytes32 hash1, bytes32 hash2, bytes32 hash3) {
+ uint120[] memory y = new uint120[](3);
+ x[0] = y[0] = uint120(-2);
+ x[1] = y[1] = uint120(-3);
+ x[2] = y[2] = uint120(-4);
+ hash1 = keccak256(x);
+ hash2 = keccak256(y);
+ hash3 = keccak256(this.f);
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ // Strangely, arrays are encoded with intra-element padding.
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(
+ dev::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))),
+ dev::keccak256(encodeArgs(u256("0xfffffffffffffffffffffffffffffe"), u256("0xfffffffffffffffffffffffffffffd"), u256("0xfffffffffffffffffffffffffffffc"))),
+ dev::keccak256(fromHex(m_contractAddress.hex() + "26121ff0"))
+ ));
+}
+
BOOST_AUTO_TEST_CASE(packed_sha256)
{
char const* sourceCode = R"(
diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol
new file mode 100644
index 00000000..9f57c3a4
--- /dev/null
+++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_internal_functions.sol
@@ -0,0 +1,11 @@
+contract C {
+ function f() public pure {
+ bytes32 h = keccak256(keccak256, f, this.f.gas, block.blockhash);
+ h;
+ }
+}
+// ----
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol
new file mode 100644
index 00000000..a7d13215
--- /dev/null
+++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol
@@ -0,0 +1,13 @@
+contract C {
+ function f() public pure {
+ bool a = address(this).call(address(this).delegatecall, super);
+ bool b = address(this).delegatecall(log0, tx, mulmod);
+ a; b;
+ }
+}
+// ----
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol
new file mode 100644
index 00000000..f27290fd
--- /dev/null
+++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_structs.sol
@@ -0,0 +1,13 @@
+contract C {
+ struct S { uint x; }
+ S s;
+ struct T { }
+ T t;
+ function f() public pure {
+ bytes32 a = sha256(s, t);
+ a;
+ }
+}
+// ----
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol
new file mode 100644
index 00000000..991b2237
--- /dev/null
+++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_types.sol
@@ -0,0 +1,16 @@
+contract C {
+ struct S { uint x; }
+ S s;
+ struct T { }
+ T t;
+ enum A { X, Y }
+ function f() public pure {
+ bool a = address(this).delegatecall(S, A, A.X, T, uint, uint[]);
+ }
+}
+// ----
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
+// TypeError: This type cannot be encoded.
diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_without_encoding_problems.sol b/test/libsolidity/syntaxTests/specialFunctions/types_without_encoding_problems.sol
new file mode 100644
index 00000000..c8364548
--- /dev/null
+++ b/test/libsolidity/syntaxTests/specialFunctions/types_without_encoding_problems.sol
@@ -0,0 +1,9 @@
+contract C {
+ uint[3] sarr;
+ function f() view public {
+ uint[3] memory arr;
+ bytes32 h = keccak256(this.f, arr, sarr);
+ h;
+ }
+}
+// ----