diff --git a/Changelog.md b/Changelog.md index fdba5a463..6f0d76d6c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -16,6 +16,7 @@ Bugfixes: * Type Checker: Make UTF8-validation a bit more sloppy to include more valid sequences. * Fixed crash concerning non-callable types. * Unused variable warnings no longer issued for variables used inside inline assembly. + * Code Generator: Fix ABI encoding of empty literal string. * Inline Assembly: Enforce function arguments when parsing functional instructions. * Fixed segfault with constant function parameters diff --git a/docs/bugs.json b/docs/bugs.json index 1a67d6262..a0c0e7c43 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,4 +1,11 @@ [ + { + "name": "SkipEmptyStringLiteral", + "summary": "If \"\" is used in a function call, the following function arguments will not be correctly passed to the function.", + "description": "If the empty string literal \"\" is used as an argument in a function call, it is skipped by the encoder. This has the effect that the encoding of all arguments following this is shifted left by 32 bytes and thus the function call data is corrupted.", + "fixed": "0.4.12", + "severity": "low" + }, { "name": "ConstantOptimizerSubtraction", "summary": "In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers.", diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 0f7346b48..1be05f3c3 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -1,6 +1,7 @@ { "0.1.0": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", @@ -15,6 +16,7 @@ }, "0.1.1": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", @@ -29,6 +31,7 @@ }, "0.1.2": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", @@ -43,6 +46,7 @@ }, "0.1.3": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", @@ -57,6 +61,7 @@ }, "0.1.4": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", @@ -71,6 +76,7 @@ }, "0.1.5": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStaleKnowledgeAboutSHA3", @@ -85,6 +91,7 @@ }, "0.1.6": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -100,6 +107,7 @@ }, "0.1.7": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -115,6 +123,7 @@ }, "0.2.0": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -130,6 +139,7 @@ }, "0.2.1": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -145,6 +155,7 @@ }, "0.2.2": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -160,6 +171,7 @@ }, "0.3.0": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -174,6 +186,7 @@ }, "0.3.1": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -187,6 +200,7 @@ }, "0.3.2": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -200,6 +214,7 @@ }, "0.3.3": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -212,6 +227,7 @@ }, "0.3.4": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -224,6 +240,7 @@ }, "0.3.5": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -236,6 +253,7 @@ }, "0.3.6": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -246,6 +264,7 @@ }, "0.4.0": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -256,6 +275,7 @@ }, "0.4.1": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -266,16 +286,20 @@ }, "0.4.10": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2017-03-15" }, "0.4.11": { - "bugs": [], + "bugs": [ + "SkipEmptyStringLiteral" + ], "released": "2017-05-03" }, "0.4.2": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage", @@ -285,6 +309,7 @@ }, "0.4.3": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "HighOrderByteCleanStorage" @@ -293,6 +318,7 @@ }, "0.4.4": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" ], @@ -300,6 +326,7 @@ }, "0.4.5": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored", "OptimizerStateKnowledgeNotResetForJumpdest" @@ -308,6 +335,7 @@ }, "0.4.6": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction", "IdentityPrecompileReturnIgnored" ], @@ -315,18 +343,21 @@ }, "0.4.7": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2016-12-15" }, "0.4.8": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2017-01-13" }, "0.4.9": { "bugs": [ + "SkipEmptyStringLiteral", "ConstantOptimizerSubtraction" ], "released": "2017-01-31" diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 3baaaddfa..bfe72961e 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -128,7 +128,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound m_context << Instruction::DUP1; storeStringData(bytesConstRef(str->value())); if (_padToWordBoundaries) - m_context << u256(((str->value().size() + 31) / 32) * 32); + m_context << u256(max(32, ((str->value().size() + 31) / 32) * 32)); else m_context << u256(str->value().size()); m_context << Instruction::ADD; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index ba507e0cb..823a8eda0 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -9469,6 +9469,29 @@ BOOST_AUTO_TEST_CASE(revert) BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(42))); } +BOOST_AUTO_TEST_CASE(literal_empty_string) +{ + char const* sourceCode = R"( + contract C { + bytes32 public x; + uint public a; + function f(bytes32 _x, uint _a) { + x = _x; + a = _a; + } + function g() { + this.f("", 2); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs()); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(2))); +} + BOOST_AUTO_TEST_CASE(scientific_notation) { char const* sourceCode = R"(