Merge pull request #4896 from ethereum/expCleanup

Exp cleanup
This commit is contained in:
chriseth 2018-09-10 14:22:11 +02:00 committed by GitHub
commit cd26fa8300
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 131 additions and 1 deletions

View File

@ -91,6 +91,9 @@ Compiler Features:
* Code Generator: Allocate and free local variables according to their scope.
* Removed ``pragma experimental "v0.5.0";``.
Critical Bugfixes:
* Code Generator: Properly perform cleanup for exponentiation and non-256 bit types.
Bugfixes:
* Build System: Support versions of CVC4 linked against CLN instead of GMP. In case of compilation issues due to the experimental SMT solver support, the solvers can be disabled when configuring the project with CMake using ``-DUSE_CVC4=OFF`` or ``-DUSE_Z3=OFF``.
* Tests: Fix chain parameters to make ipc tests work with newer versions of cpp-ethereum.

View File

@ -1,4 +1,12 @@
[
{
"name": "ExpExponentCleanup",
"summary": "Using the ** operator with an exponent of type shorter than 256 bits can result in unexpected values.",
"description": "Higher order bits in the exponent are not properly cleaned before the EXP opcode is applied if the type of the exponent expression is smaller than 256 bits and not smaller than the type of the base. In that case, the result might be larger than expected if the exponent is assumed to lie within the value range of the type. Literal numbers as exponents are unaffected as are exponents or bases of type uint256.",
"fixed": "0.4.25",
"severity": "medium/high",
"check": {"regex-source": "[^/]\\*\\* *[^/0-9 ]"}
},
{
"name": "EventStructWrongData",
"summary": "Using structs in events logged wrong data.",

View File

@ -1,6 +1,7 @@
{
"0.1.0": {
"bugs": [
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
"SkipEmptyStringLiteral",
@ -18,6 +19,7 @@
},
"0.1.1": {
"bugs": [
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
"SkipEmptyStringLiteral",
@ -35,6 +37,7 @@
},
"0.1.2": {
"bugs": [
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
"SkipEmptyStringLiteral",
@ -52,6 +55,7 @@
},
"0.1.3": {
"bugs": [
"ExpExponentCleanup",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
"SkipEmptyStringLiteral",
@ -69,6 +73,7 @@
},
"0.1.4": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -87,6 +92,7 @@
},
"0.1.5": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -105,6 +111,7 @@
},
"0.1.6": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -124,6 +131,7 @@
},
"0.1.7": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -143,6 +151,7 @@
},
"0.2.0": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -162,6 +171,7 @@
},
"0.2.1": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -181,6 +191,7 @@
},
"0.2.2": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"ECRecoverMalformedInput",
@ -200,6 +211,7 @@
},
"0.3.0": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -219,6 +231,7 @@
},
"0.3.1": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -237,6 +250,7 @@
},
"0.3.2": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -255,6 +269,7 @@
},
"0.3.3": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -272,6 +287,7 @@
},
"0.3.4": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -289,6 +305,7 @@
},
"0.3.5": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -306,6 +323,7 @@
},
"0.3.6": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -321,6 +339,7 @@
},
"0.4.0": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -336,6 +355,7 @@
},
"0.4.1": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -351,6 +371,7 @@
},
"0.4.10": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -362,6 +383,7 @@
},
"0.4.11": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -372,6 +394,7 @@
},
"0.4.12": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -381,6 +404,7 @@
},
"0.4.13": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -390,6 +414,7 @@
},
"0.4.14": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue"
@ -398,6 +423,7 @@
},
"0.4.15": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector"
],
@ -405,6 +431,7 @@
},
"0.4.16": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector"
],
@ -412,6 +439,7 @@
},
"0.4.17": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector"
@ -420,6 +448,7 @@
},
"0.4.18": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
@ -427,6 +456,7 @@
},
"0.4.19": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
@ -434,6 +464,7 @@
},
"0.4.2": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -448,6 +479,7 @@
},
"0.4.20": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
@ -455,6 +487,7 @@
},
"0.4.21": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData",
"NestedArrayFunctionCallDecoder"
],
@ -462,6 +495,7 @@
},
"0.4.22": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData",
"OneOfTwoConstructorsSkipped"
],
@ -469,18 +503,21 @@
},
"0.4.23": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData"
],
"released": "2018-04-19"
},
"0.4.24": {
"bugs": [
"ExpExponentCleanup",
"EventStructWrongData"
],
"released": "2018-05-16"
},
"0.4.3": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -494,6 +531,7 @@
},
"0.4.4": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -506,6 +544,7 @@
},
"0.4.5": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -519,6 +558,7 @@
},
"0.4.6": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -531,6 +571,7 @@
},
"0.4.7": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -542,6 +583,7 @@
},
"0.4.8": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",
@ -553,6 +595,7 @@
},
"0.4.9": {
"bugs": [
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
"DelegateCallReturnValue",

View File

@ -2138,7 +2138,9 @@ bool ExpressionCompiler::cleanupNeededForOp(Type::Category _type, Token::Value _
{
if (Token::isCompareOp(_op) || Token::isShiftOp(_op))
return true;
else if (_type == Type::Category::Integer && (_op == Token::Div || _op == Token::Mod))
else if (_type == Type::Category::Integer && (_op == Token::Div || _op == Token::Mod || _op == Token::Exp))
// We need cleanup for EXP because 0**0 == 1, but 0**0x100 == 0
// It would suffice to clean the exponent, though.
return true;
else
return false;

View File

@ -68,6 +68,40 @@ function f() m(uint[2][2]) { }
function f() returns (uint, uint) { uint[2][2] memory x; }
# ExpExponentCleanup
## buggy
x ** y
--
x ** uint8(y)
--
x**y
## fine
x ** 2
--
x**2
--
x**200
--
/** bla **/
--
/**/
# EventStructWrongData
## buggy

View File

@ -11870,6 +11870,46 @@ BOOST_AUTO_TEST_CASE(shift_bytes_cleanup)
ABI_CHECK(callContractFunction("right(uint8)", 8 * 8), encodeArgs(string(8, 0) + "123456789012"));
}
BOOST_AUTO_TEST_CASE(exp_cleanup)
{
char const* sourceCode = R"(
contract C {
function f() public pure returns (uint8 x) {
uint8 y = uint8(2) ** uint8(8);
return 0 ** y;
}
}
)";
compileAndRun(sourceCode, 0, "C");
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1)));
}
BOOST_AUTO_TEST_CASE(exp_cleanup_direct)
{
char const* sourceCode = R"(
contract C {
function f() public pure returns (uint8 x) {
return uint8(0) ** uint8(uint8(2) ** uint8(8));
}
}
)";
compileAndRun(sourceCode, 0, "C");
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1)));
}
BOOST_AUTO_TEST_CASE(exp_cleanup_nonzero_base)
{
char const* sourceCode = R"(
contract C {
function f() public pure returns (uint8 x) {
return uint8(0x166) ** uint8(uint8(2) ** uint8(8));
}
}
)";
compileAndRun(sourceCode, 0, "C");
ABI_CHECK(callContractFunction("f()"), encodeArgs(u256(0x1)));
}
BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign)
{
char const* sourceCode = R"(