mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4938 from ethereum/expCleanup0425
[backport] Exp cleanup
This commit is contained in:
commit
6402b83826
@ -1,6 +1,7 @@
|
||||
### 0.4.25 (unreleased)
|
||||
|
||||
Bugfixes:
|
||||
Important Bugfixes:
|
||||
* Code Generator: Properly perform cleanup for exponentiation and non-256 bit types.
|
||||
* Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values.
|
||||
* Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values.
|
||||
* Parser: Treat unicode line endings as terminating strings and single-line comments.
|
||||
|
@ -7,6 +7,14 @@
|
||||
"fixed": "0.4.25",
|
||||
"severity": "very low"
|
||||
},
|
||||
{
|
||||
"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": "OneOfTwoConstructorsSkipped",
|
||||
"summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.",
|
||||
|
@ -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",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
"SkipEmptyStringLiteral",
|
||||
@ -86,6 +91,7 @@
|
||||
},
|
||||
"0.1.5": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
"SkipEmptyStringLiteral",
|
||||
@ -103,6 +109,7 @@
|
||||
},
|
||||
"0.1.6": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
"SkipEmptyStringLiteral",
|
||||
@ -121,6 +128,7 @@
|
||||
},
|
||||
"0.1.7": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
"SkipEmptyStringLiteral",
|
||||
@ -139,6 +147,7 @@
|
||||
},
|
||||
"0.2.0": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
"SkipEmptyStringLiteral",
|
||||
@ -157,6 +166,7 @@
|
||||
},
|
||||
"0.2.1": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
"SkipEmptyStringLiteral",
|
||||
@ -175,6 +185,7 @@
|
||||
},
|
||||
"0.2.2": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"ECRecoverMalformedInput",
|
||||
"SkipEmptyStringLiteral",
|
||||
@ -193,6 +204,7 @@
|
||||
},
|
||||
"0.3.0": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -211,6 +223,7 @@
|
||||
},
|
||||
"0.3.1": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -228,6 +241,7 @@
|
||||
},
|
||||
"0.3.2": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -245,6 +259,7 @@
|
||||
},
|
||||
"0.3.3": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -261,6 +276,7 @@
|
||||
},
|
||||
"0.3.4": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -277,6 +293,7 @@
|
||||
},
|
||||
"0.3.5": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -293,6 +310,7 @@
|
||||
},
|
||||
"0.3.6": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -307,6 +325,7 @@
|
||||
},
|
||||
"0.4.0": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -321,6 +340,7 @@
|
||||
},
|
||||
"0.4.1": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -335,6 +355,7 @@
|
||||
},
|
||||
"0.4.10": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -345,6 +366,7 @@
|
||||
},
|
||||
"0.4.11": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -354,6 +376,7 @@
|
||||
},
|
||||
"0.4.12": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput"
|
||||
@ -362,6 +385,7 @@
|
||||
},
|
||||
"0.4.13": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput"
|
||||
@ -370,6 +394,7 @@
|
||||
},
|
||||
"0.4.14": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue"
|
||||
],
|
||||
@ -377,12 +402,14 @@
|
||||
},
|
||||
"0.4.15": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector"
|
||||
],
|
||||
"released": "2017-08-08"
|
||||
},
|
||||
"0.4.16": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector"
|
||||
],
|
||||
"released": "2017-08-24"
|
||||
@ -390,24 +417,28 @@
|
||||
"0.4.17": {
|
||||
"bugs": [
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector"
|
||||
],
|
||||
"released": "2017-09-21"
|
||||
},
|
||||
"0.4.18": {
|
||||
"bugs": [
|
||||
"EventStructWrongData"
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup"
|
||||
],
|
||||
"released": "2017-10-18"
|
||||
},
|
||||
"0.4.19": {
|
||||
"bugs": [
|
||||
"EventStructWrongData"
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup"
|
||||
],
|
||||
"released": "2017-11-30"
|
||||
},
|
||||
"0.4.2": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -421,37 +452,43 @@
|
||||
},
|
||||
"0.4.20": {
|
||||
"bugs": [
|
||||
"EventStructWrongData"
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup"
|
||||
],
|
||||
"released": "2018-02-14"
|
||||
},
|
||||
"0.4.21": {
|
||||
"bugs": [
|
||||
"EventStructWrongData"
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup"
|
||||
],
|
||||
"released": "2018-03-07"
|
||||
},
|
||||
"0.4.22": {
|
||||
"bugs": [
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup",
|
||||
"OneOfTwoConstructorsSkipped"
|
||||
],
|
||||
"released": "2018-04-16"
|
||||
},
|
||||
"0.4.23": {
|
||||
"bugs": [
|
||||
"EventStructWrongData"
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup"
|
||||
],
|
||||
"released": "2018-04-19"
|
||||
},
|
||||
"0.4.24": {
|
||||
"bugs": [
|
||||
"EventStructWrongData"
|
||||
"EventStructWrongData",
|
||||
"ExpExponentCleanup"
|
||||
],
|
||||
"released": "2018-05-16"
|
||||
},
|
||||
"0.4.3": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -464,6 +501,7 @@
|
||||
},
|
||||
"0.4.4": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -475,6 +513,7 @@
|
||||
},
|
||||
"0.4.5": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -487,6 +526,7 @@
|
||||
},
|
||||
"0.4.6": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -498,6 +538,7 @@
|
||||
},
|
||||
"0.4.7": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -508,6 +549,7 @@
|
||||
},
|
||||
"0.4.8": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
@ -518,6 +560,7 @@
|
||||
},
|
||||
"0.4.9": {
|
||||
"bugs": [
|
||||
"ExpExponentCleanup",
|
||||
"ZeroFunctionSelector",
|
||||
"DelegateCallReturnValue",
|
||||
"ECRecoverMalformedInput",
|
||||
|
@ -2069,7 +2069,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;
|
||||
|
148
test/buglist_test_vectors.md
Normal file
148
test/buglist_test_vectors.md
Normal file
@ -0,0 +1,148 @@
|
||||
# NestedArrayFunctionCallDecoder
|
||||
|
||||
## buggy
|
||||
|
||||
function f() pure returns (uint[2][2]) { }
|
||||
|
||||
--
|
||||
|
||||
function f() returns (uint[2][2] a) { }
|
||||
|
||||
--
|
||||
|
||||
function f() returns (uint x, uint[200][2] a) { }
|
||||
|
||||
--
|
||||
|
||||
function f() returns (uint[200][2] a, uint x) { }
|
||||
|
||||
--
|
||||
|
||||
function f() returns (uint[200][2] a, uint x);
|
||||
|
||||
--
|
||||
|
||||
function f() returns (
|
||||
uint
|
||||
[
|
||||
200
|
||||
]
|
||||
[2]
|
||||
a, uint x);
|
||||
|
||||
--
|
||||
|
||||
function f() returns (
|
||||
uint
|
||||
[
|
||||
ContractName.ConstantName
|
||||
]
|
||||
[2]
|
||||
a, uint x);
|
||||
|
||||
## fine
|
||||
|
||||
function f() returns (uint[2]) { }
|
||||
|
||||
--
|
||||
|
||||
function f() public pure returns (uint[2][] a) { }
|
||||
|
||||
--
|
||||
|
||||
function f() public pure returns (uint[ 2 ] [ ] a) { }
|
||||
|
||||
--
|
||||
|
||||
function f() public pure returns (uint x, uint[] a) { }
|
||||
|
||||
--
|
||||
|
||||
function f(uint[2][2]) { }
|
||||
|
||||
--
|
||||
|
||||
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
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C
|
||||
{
|
||||
struct S { uint x; }
|
||||
event E(S);
|
||||
event F(S);
|
||||
enum A { B, C }
|
||||
event G(A);
|
||||
function f(S s);
|
||||
}
|
||||
|
||||
--
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C
|
||||
{
|
||||
struct S { uint x; }
|
||||
event E(S indexed);
|
||||
event F(uint, S, bool);
|
||||
}
|
||||
|
||||
## fine
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C
|
||||
{
|
||||
struct S { uint x; }
|
||||
enum A { B, C }
|
||||
event G(A);
|
||||
}
|
||||
|
||||
--
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C
|
||||
{
|
||||
struct S { uint x; }
|
||||
function f(S s);
|
||||
S s1;
|
||||
}
|
@ -10743,6 +10743,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"(
|
||||
|
Loading…
Reference in New Issue
Block a user