Merge pull request #6317 from ethereum/byte_optimization_bugfix

Fixes bug in byte optimization rule and adds tests.
This commit is contained in:
Alex Beregszaszi 2019-03-21 21:49:34 +00:00 committed by GitHub
commit ed1ad2fc14
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 2 deletions

View File

@ -1,5 +1,8 @@
### 0.5.7 (unreleased)
Important Bugfixes:
* Optimizer: Fix wrong ordering of arguments in byte optimization rule for constants.
Language Features:

View File

@ -1,4 +1,15 @@
[
{
"name": "IncorrectByteInstructionOptimization",
"summary": "The optimizer incorrectly handles byte opcodes whose second argument is 31 or a constant expression that evaluates to 31. This can result in unexpected values.",
"description": "The optimizer incorrectly handles byte opcodes that use the constant 31 as second argument. This can happen when performing index access on bytesNN types with a compile-time constant value (not index) of 31 or when using the byte opcode in inline assembly.",
"introduced": "0.5.5",
"fixed": "0.5.7",
"severity": "very low",
"conditions": {
"optimizer": true
}
},
{
"name": "DoubleShiftSizeOverflow",
"summary": "Double bitwise shifts by large constants whose sum overflows 256 bits can result in unexpected values.",

View File

@ -631,12 +631,15 @@
},
"0.5.5": {
"bugs": [
"IncorrectByteInstructionOptimization",
"DoubleShiftSizeOverflow"
],
"released": "2019-03-05"
},
"0.5.6": {
"bugs": [],
"bugs": [
"IncorrectByteInstructionOptimization"
],
"released": "2019-03-13"
}
}

View File

@ -153,7 +153,7 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart2(
{{Instruction::GT, {0, X}}, [=]{ return u256(0); }, true},
{{Instruction::LT, {X, 0}}, [=]{ return u256(0); }, true},
{{Instruction::AND, {{Instruction::BYTE, {X, Y}}, {u256(0xff)}}}, [=]() -> Pattern { return {Instruction::BYTE, {X, Y}}; }, false},
{{Instruction::BYTE, {X, 31}}, [=]() -> Pattern { return {Instruction::AND, {X, u256(0xff)}}; }, false}
{{Instruction::BYTE, {31, X}}, [=]() -> Pattern { return {Instruction::AND, {X, u256(0xff)}}; }, false}
};
}

View File

@ -268,6 +268,26 @@ BOOST_AUTO_TEST_CASE(cse_double_shift_left_overflow)
}
}
BOOST_AUTO_TEST_CASE(cse_byte_ordering_bug)
{
AssemblyItems input{
u256(31),
Instruction::CALLVALUE,
Instruction::BYTE
};
checkCSE(input, {u256(31), Instruction::CALLVALUE, Instruction::BYTE});
}
BOOST_AUTO_TEST_CASE(cse_byte_ordering_fix)
{
AssemblyItems input{
Instruction::CALLVALUE,
u256(31),
Instruction::BYTE
};
checkCSE(input, {u256(0xff), Instruction::CALLVALUE, Instruction::AND});
}
BOOST_AUTO_TEST_CASE(cse_storage)
{
AssemblyItems input{

View File

@ -10495,6 +10495,27 @@ BOOST_AUTO_TEST_CASE(fixed_bytes_length_access)
ABI_CHECK(callContractFunction("f(bytes32)", "789"), encodeArgs(u256(32), u256(16), u256(8)));
}
BOOST_AUTO_TEST_CASE(byte_optimization_bug)
{
char const* sourceCode = R"(
contract C {
function f(uint x) public returns (uint a) {
assembly {
a := byte(x, 31)
}
}
function g(uint x) public returns (uint a) {
assembly {
a := byte(31, x)
}
}
}
)";
compileAndRun(sourceCode, 0, "C");
ABI_CHECK(callContractFunction("f(uint256)", u256(2)), encodeArgs(u256(0)));
ABI_CHECK(callContractFunction("g(uint256)", u256(2)), encodeArgs(u256(2)));
}
BOOST_AUTO_TEST_CASE(inline_assembly_write_to_stack)
{
char const* sourceCode = R"(