From ae9013f3679abca2a895410db621263fc9c22390 Mon Sep 17 00:00:00 2001 From: Christian Date: Sun, 22 Feb 2015 19:15:41 +0100 Subject: [PATCH 1/3] Implementation of index access. --- SolidityEndToEndTest.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 20bc81599..0c4c79aca 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -2667,6 +2667,33 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) == encodeArgs(12, (8 + 9) * 3, 13, u256(innercalldata1.length()))); } +BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) +{ + char const* sourceCode = R"( + contract c { + struct Data { uint x; uint y; } + Data[2**10] data; + uint[2**10 + 3] ids; + function setIDStatic(uint id) { ids[2] = id; } + function setID(uint index, uint id) { ids[index] = id; } + function setData(uint index, uint x, uint y) { data[index].x = x; data[index].y = y; } + function getID(uint index) returns (uint) { return ids[index]; } + function getData(uint index) returns (uint x, uint y) { x = data[index].x; y = data[index].y; } + function getLengths() returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); + BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); + BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); + BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); + BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(u256(1) << 10, (u256(1) << 10) + 3)); +} + BOOST_AUTO_TEST_SUITE_END() } From a5eb2a3990626a384bd48a070a02dda0174d5d95 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 23 Feb 2015 01:31:05 +0100 Subject: [PATCH 2/3] Index and length access for dynamic arrays. --- SolidityEndToEndTest.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 0c4c79aca..6f85aec9e 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -2694,6 +2694,35 @@ BOOST_AUTO_TEST_CASE(fixed_arrays_in_storage) BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(u256(1) << 10, (u256(1) << 10) + 3)); } +BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) +{ + char const* sourceCode = R"( + contract c { + struct Data { uint x; uint y; } + Data[] data; + uint[] ids; + function setIDStatic(uint id) { ids[2] = id; } + function setID(uint index, uint id) { ids[index] = id; } + function setData(uint index, uint x, uint y) { data[index].x = x; data[index].y = y; } + function getID(uint index) returns (uint) { return ids[index]; } + function getData(uint index) returns (uint x, uint y) { x = data[index].x; y = data[index].y; } + function getLengths() returns (uint l1, uint l2) { l1 = data.length; l2 = ids.length; } + function setLengths(uint l1, uint l2) { data.length = l1; ids.length = l2; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); + BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); + BOOST_CHECK(callContractFunction("getID(uint256)", 7) == encodeArgs(8)); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 7, 8, 9) == bytes()); + BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); + BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); + BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); + BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes()); + BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49)); +} + BOOST_AUTO_TEST_SUITE_END() } From ed08c6866470c4a0f5255cb488bb3e0a869bc5e1 Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 23 Feb 2015 18:21:17 +0100 Subject: [PATCH 3/3] Out-of-bounds checking. --- SolidityEndToEndTest.cpp | 49 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/SolidityEndToEndTest.cpp b/SolidityEndToEndTest.cpp index 6f85aec9e..f43692110 100644 --- a/SolidityEndToEndTest.cpp +++ b/SolidityEndToEndTest.cpp @@ -2711,6 +2711,9 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) } )"; compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(0, 0)); + BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes()); + BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49)); BOOST_CHECK(callContractFunction("setIDStatic(uint256)", 11) == bytes()); BOOST_CHECK(callContractFunction("getID(uint256)", 2) == encodeArgs(11)); BOOST_CHECK(callContractFunction("setID(uint256,uint256)", 7, 8) == bytes()); @@ -2719,8 +2722,50 @@ BOOST_AUTO_TEST_CASE(dynamic_arrays_in_storage) BOOST_CHECK(callContractFunction("setData(uint256,uint256,uint256)", 8, 10, 11) == bytes()); BOOST_CHECK(callContractFunction("getData(uint256)", 7) == encodeArgs(8, 9)); BOOST_CHECK(callContractFunction("getData(uint256)", 8) == encodeArgs(10, 11)); - BOOST_CHECK(callContractFunction("setLengths(uint256,uint256)", 48, 49) == bytes()); - BOOST_CHECK(callContractFunction("getLengths()") == encodeArgs(48, 49)); +} + +BOOST_AUTO_TEST_CASE(fixed_out_of_bounds_array_access) +{ + char const* sourceCode = R"( + contract c { + uint[4] data; + function set(uint index, uint value) returns (bool) { data[index] = value; return true; } + function get(uint index) returns (uint) { return data[index]; } + function length() returns (uint) { return data.length; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 5) == bytes()); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 400, 5) == bytes()); + BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); + BOOST_CHECK(callContractFunction("get(uint256)", 4) == bytes()); + BOOST_CHECK(callContractFunction("get(uint256)", 400) == bytes()); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); +} + +BOOST_AUTO_TEST_CASE(dynamic_out_of_bounds_array_access) +{ + char const* sourceCode = R"( + contract c { + uint[] data; + function enlarge(uint amount) returns (uint) { return data.length += amount; } + function set(uint index, uint value) returns (bool) { data[index] = value; return true; } + function get(uint index) returns (uint) { return data[index]; } + function length() returns (uint) { return data.length; } + } + )"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(0)); + BOOST_CHECK(callContractFunction("get(uint256)", 3) == bytes()); + BOOST_CHECK(callContractFunction("enlarge(uint256)", 4) == encodeArgs(4)); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 3, 4) == encodeArgs(true)); + BOOST_CHECK(callContractFunction("get(uint256)", 3) == encodeArgs(4)); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); + BOOST_CHECK(callContractFunction("set(uint256,uint256)", 4, 8) == bytes()); + BOOST_CHECK(callContractFunction("length()") == encodeArgs(4)); } BOOST_AUTO_TEST_SUITE_END()