diff --git a/libraries/fc/include/fc/container/deque_fwd.hpp b/libraries/fc/include/fc/container/deque_fwd.hpp index 80359ea67c..246114cd5e 100644 --- a/libraries/fc/include/fc/container/deque_fwd.hpp +++ b/libraries/fc/include/fc/container/deque_fwd.hpp @@ -8,6 +8,6 @@ namespace fc { template void pack( Stream& s, const std::deque& value ); template - void unpack( Stream& s, std::deque& value ); + void unpack( Stream& s, std::deque& value, uint32_t depth = 0 ); } } // namespace fc diff --git a/libraries/fc/include/fc/container/flat.hpp b/libraries/fc/include/fc/container/flat.hpp index fce20d4694..c24bb193f4 100644 --- a/libraries/fc/include/fc/container/flat.hpp +++ b/libraries/fc/include/fc/container/flat.hpp @@ -78,6 +78,7 @@ namespace fc { FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int size; unpack( s, size, depth ); + value.clear(); if( !std::is_fundamental::value ) { for ( size_t i = 0; i < size.value; i++ ) { diff --git a/libraries/fc/include/fc/io/raw.hpp b/libraries/fc/include/fc/io/raw.hpp index a52e2c1360..798aa45186 100644 --- a/libraries/fc/include/fc/io/raw.hpp +++ b/libraries/fc/include/fc/io/raw.hpp @@ -524,6 +524,7 @@ namespace fc { FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int size; fc::raw::unpack( s, size, depth ); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); + value.clear(); for ( size_t i = 0; i < size.value; i++ ) { T tmp; @@ -549,6 +550,7 @@ namespace fc { FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int size; fc::raw::unpack( s, size ); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); + value.clear(); for ( size_t i = 0; i < size.value; i++ ) { T tmp; @@ -573,6 +575,7 @@ namespace fc { depth++; FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int size; fc::raw::unpack( s, size, depth ); + value.clear(); for( uint64_t i = 0; i < size.value; ++i ) { typename std::set::value_type tmp; @@ -597,6 +600,7 @@ namespace fc { depth++; FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int size; fc::raw::unpack( s, size, depth ); + value.clear(); for( uint64_t i = 0; i < size.value; ++i ) { typename std::multiset::value_type tmp; diff --git a/libraries/fc/include/fc/io/raw_fwd.hpp b/libraries/fc/include/fc/io/raw_fwd.hpp index 646219a516..80e19760b9 100644 --- a/libraries/fc/include/fc/io/raw_fwd.hpp +++ b/libraries/fc/include/fc/io/raw_fwd.hpp @@ -53,9 +53,6 @@ namespace fc { template void pack( Stream& s, const static_variant& sv ); template void unpack( Stream& s, static_variant& sv, uint32_t depth = 0 ); - template inline void pack( Stream& s, const std::deque& value ); - template inline void unpack( Stream& s, std::deque& value, uint32_t depth = 0 ); - template inline void pack( Stream& s, const std::unordered_map& value ); template inline void unpack( Stream& s, std::unordered_map& value, uint32_t depth = 0 ); diff --git a/libraries/fc/include/fc/io/raw_variant.hpp b/libraries/fc/include/fc/io/raw_variant.hpp index 53b8898539..f3f0b77a97 100644 --- a/libraries/fc/include/fc/io/raw_variant.hpp +++ b/libraries/fc/include/fc/io/raw_variant.hpp @@ -137,7 +137,6 @@ namespace fc { namespace raw { unpack( s, vs, depth ); mutable_variant_object mvo; - mvo.reserve(vs.value); for( uint32_t i = 0; i < vs.value; ++i ) { fc::string key; diff --git a/libraries/protocol/include/steem/protocol/config.hpp b/libraries/protocol/include/steem/protocol/config.hpp index 4647495052..cc623436fb 100644 --- a/libraries/protocol/include/steem/protocol/config.hpp +++ b/libraries/protocol/include/steem/protocol/config.hpp @@ -43,7 +43,7 @@ #else // IS LIVE STEEM NETWORK -#define STEEM_BLOCKCHAIN_VERSION ( version(0, 20, 7) ) +#define STEEM_BLOCKCHAIN_VERSION ( version(0, 20, 8) ) #define STEEM_INIT_PUBLIC_KEY_STR "STM8GC13uCZbP44HzMLV6zPZGwVQ8Nt4Kji8PapsPiNq1BK153XTX" #define STEEM_CHAIN_ID fc::sha256() diff --git a/tests/tests/serialization_tests.cpp b/tests/tests/serialization_tests.cpp index 8dba4b3dce..7192105b03 100644 --- a/tests/tests/serialization_tests.cpp +++ b/tests/tests/serialization_tests.cpp @@ -604,5 +604,112 @@ BOOST_AUTO_TEST_CASE( legacy_operation_test ) FC_LOG_AND_RETHROW() } +BOOST_AUTO_TEST_CASE( unpack_clear_test ) +{ + try + { + std::stringstream ss1; + std::stringstream ss2; + + signed_block b1; + + for ( int i = 0; i < 10; i++ ) + { + signed_transaction tx; + + vote_operation op; + op.voter = "alice"; + op.author = "bob"; + op.permlink = "permlink1"; + op.weight = STEEM_100_PERCENT; + tx.operations.push_back( op ); + + vote_operation op2; + op2.voter = "charlie"; + op2.author = "sam"; + op2.permlink = "permlink2"; + op2.weight = STEEM_100_PERCENT; + tx.operations.push_back( op2 ); + + tx.ref_block_num = 1000; + tx.ref_block_prefix = 1000000000; + tx.expiration = fc::time_point_sec( 1514764800 + i ); + + b1.transactions.push_back( tx ); + } + + signed_block b2; + + for ( int i = 0; i < 20; i++ ) + { + signed_transaction tx; + vote_operation op; + op.voter = "dave"; + op.author = "greg"; + op.permlink = "foobar"; + op.weight = STEEM_100_PERCENT/2; + tx.ref_block_num = 4000; + tx.ref_block_prefix = 4000000000; + tx.expiration = fc::time_point_sec( 1714764800 + i ); + tx.operations.push_back( op ); + + b2.transactions.push_back( tx ); + } + + fc::raw::pack( ss2, b2 ); + fc::raw::pack( ss1, b1 ); + + signed_block unpacked_block; + fc::raw::unpack( ss2, unpacked_block ); + + // This operation should completely overwrite signed block 'b2' + fc::raw::unpack( ss1, unpacked_block ); + + BOOST_REQUIRE( b1.transactions.size() == unpacked_block.transactions.size() ); + for ( size_t i = 0; i < unpacked_block.transactions.size(); i++ ) + { + signed_transaction tx = unpacked_block.transactions[ i ]; + BOOST_REQUIRE( unpacked_block.transactions[ i ].operations.size() == b1.transactions[ i ].operations.size() ); + + vote_operation op = tx.operations[ 0 ].get< vote_operation >(); + BOOST_REQUIRE( op.voter == "alice" ); + BOOST_REQUIRE( op.author == "bob" ); + BOOST_REQUIRE( op.permlink == "permlink1" ); + BOOST_REQUIRE( op.weight == STEEM_100_PERCENT ); + + vote_operation op2 = tx.operations[ 1 ].get< vote_operation >(); + BOOST_REQUIRE( op2.voter == "charlie" ); + BOOST_REQUIRE( op2.author == "sam" ); + BOOST_REQUIRE( op2.permlink == "permlink2" ); + BOOST_REQUIRE( op2.weight == STEEM_100_PERCENT ); + + BOOST_REQUIRE( tx.ref_block_num == 1000 ); + BOOST_REQUIRE( tx.ref_block_prefix == 1000000000 ); + BOOST_REQUIRE( tx.expiration == fc::time_point_sec( 1514764800 + i ) ); + } + } + FC_LOG_AND_RETHROW(); +} + +BOOST_AUTO_TEST_CASE( unpack_recursion_test ) +{ + try + { + std::stringstream ss; + int recursion_level = 100000; + uint64_t allocation_per_level = 500000; + + for ( int i = 0; i < recursion_level; i++ ) + { + fc::raw::pack( ss, unsigned_int( allocation_per_level ) ); + fc::raw::pack( ss, static_cast< uint8_t >( variant::array_type ) ); + } + + std::vector< fc::variant > v; + STEEM_REQUIRE_THROW( fc::raw::unpack( ss, v ), fc::assert_exception ); + } + FC_LOG_AND_RETHROW(); +} + BOOST_AUTO_TEST_SUITE_END() #endif