diff --git a/libraries/chain/include/steem/chain/steem_object_types.hpp b/libraries/chain/include/steem/chain/steem_object_types.hpp index 3c5379c707..554b2c93a6 100644 --- a/libraries/chain/include/steem/chain/steem_object_types.hpp +++ b/libraries/chain/include/steem/chain/steem_object_types.hpp @@ -196,7 +196,7 @@ namespace fc s.write( (const char*)&id._id, sizeof(id._id) ); } template - inline void unpack( Stream& s, chainbase::oid& id ) + inline void unpack( Stream& s, chainbase::oid& id, uint32_t ) { s.read( (char*)&id._id, sizeof(id._id)); } diff --git a/libraries/fc/include/fc/container/flat.hpp b/libraries/fc/include/fc/container/flat.hpp index 48fdf75c29..fce20d4694 100644 --- a/libraries/fc/include/fc/container/flat.hpp +++ b/libraries/fc/include/fc/container/flat.hpp @@ -18,15 +18,16 @@ namespace fc { } } template - inline void unpack( Stream& s, flat_set& value ) { - unsigned_int size; unpack( s, size ); + inline void unpack( Stream& s, flat_set& value, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + unsigned_int size; unpack( s, size, depth ); value.clear(); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); - value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { T tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); value.insert( std::move(tmp) ); } } @@ -41,16 +42,17 @@ namespace fc { } } template - inline void unpack( Stream& s, flat_map& value ) + inline void unpack( Stream& s, flat_map& value, uint32_t depth ) { - unsigned_int size; unpack( s, size ); + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + unsigned_int size; unpack( s, size, depth ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); - value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { std::pair tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); value.insert( std::move(tmp) ); } } @@ -71,13 +73,18 @@ namespace fc { } template - void unpack( Stream& s, bip::vector& value ) { + void unpack( Stream& s, bip::vector& value, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int size; - unpack( s, size ); - value.resize( size ); + unpack( s, size, depth ); if( !std::is_fundamental::value ) { - for( auto& item : value ) - unpack( s, item ); + for ( size_t i = 0; i < size.value; i++ ) + { + T tmp; + unpack( s, tmp, depth ); + value.emplace_back( std::move( tmp ) ); + } } else { s.read( (char*)value.data(), value.size() ); } diff --git a/libraries/fc/include/fc/container/flat_fwd.hpp b/libraries/fc/include/fc/container/flat_fwd.hpp index 98dd9547be..20d5cb175b 100644 --- a/libraries/fc/include/fc/container/flat_fwd.hpp +++ b/libraries/fc/include/fc/container/flat_fwd.hpp @@ -13,17 +13,21 @@ namespace fc { template void pack( Stream& s, const flat_set& value ); template - void unpack( Stream& s, flat_set& value ); + void unpack( Stream& s, flat_set& value, uint32_t depth = 0 ); template void pack( Stream& s, const flat_map& value ); template - void unpack( Stream& s, flat_map& value ) ; + void unpack( Stream& s, flat_map& value, uint32_t depth = 0 ) ; + template + void pack( Stream& s, const flat_map& value ); + template + void unpack( Stream& s, flat_map& value, uint32_t depth = 0 ); template void pack( Stream& s, const bip::vector& value ); template - void unpack( Stream& s, bip::vector& value ); + void unpack( Stream& s, bip::vector& value, uint32_t depth = 0 ); } // namespace raw } // fc diff --git a/libraries/fc/include/fc/fixed_string.hpp b/libraries/fc/include/fc/fixed_string.hpp index 6a30d58a1b..e73c34084a 100644 --- a/libraries/fc/include/fc/fixed_string.hpp +++ b/libraries/fc/include/fc/fixed_string.hpp @@ -105,9 +105,10 @@ namespace fc { } template - inline void unpack( Stream& s, fc::fixed_string& u ) { + inline void unpack( Stream& s, fc::fixed_string& u, uint32_t depth ) { + depth++; unsigned_int size; - fc::raw::unpack( s, size ); + fc::raw::unpack( s, size, depth ); if( size.value > 0 ) { if( size.value > sizeof(Storage) ) { s.read( (char*)&u.data, sizeof(Storage) ); diff --git a/libraries/fc/include/fc/interprocess/container.hpp b/libraries/fc/include/fc/interprocess/container.hpp index cd9259b6b2..fa1c240dab 100644 --- a/libraries/fc/include/fc/interprocess/container.hpp +++ b/libraries/fc/include/fc/interprocess/container.hpp @@ -135,12 +135,18 @@ namespace fc { } } template - inline void unpack( Stream& s, bip::vector& value ) { + inline void unpack( Stream& s, bip::vector& value, uint32_t depth = 0 ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int size; - unpack( s, size ); - value.clear(); value.resize(size); - for( auto& item : value ) - fc::raw::unpack( s, item ); + unpack( s, size, depth ); + value.clear(); + for ( size_t i = 0; i < size.value; i++ ) + { + T tmp; + fc::raw::unpack( s, tmp, depth ); + value.emplace_back( std::move( tmp ) ); + } } } diff --git a/libraries/fc/include/fc/io/enum_type.hpp b/libraries/fc/include/fc/io/enum_type.hpp index e41770ced1..fc546acac7 100644 --- a/libraries/fc/include/fc/io/enum_type.hpp +++ b/libraries/fc/include/fc/io/enum_type.hpp @@ -69,10 +69,12 @@ namespace fc } template - inline void unpack( Stream& s, fc::enum_type& tp ) + inline void unpack( Stream& s, fc::enum_type& tp, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); IntType t; - fc::raw::unpack( s, t ); + fc::raw::unpack( s, t, depth ); tp = t; } } diff --git a/libraries/fc/include/fc/io/raw.hpp b/libraries/fc/include/fc/io/raw.hpp index c143915630..a52e2c1360 100644 --- a/libraries/fc/include/fc/io/raw.hpp +++ b/libraries/fc/include/fc/io/raw.hpp @@ -34,16 +34,18 @@ namespace fc { fc::raw::pack( s, e.get_log() ); } template - inline void unpack( Stream& s, fc::exception& e ) + inline void unpack( Stream& s, fc::exception& e, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); int64_t code; std::string name, what; log_messages msgs; - fc::raw::unpack( s, code ); - fc::raw::unpack( s, name ); - fc::raw::unpack( s, what ); - fc::raw::unpack( s, msgs ); + fc::raw::unpack( s, code, depth ); + fc::raw::unpack( s, name, depth ); + fc::raw::unpack( s, what, depth ); + fc::raw::unpack( s, msgs, depth ); e = fc::exception( fc::move(msgs), code, name, what ); } @@ -54,10 +56,12 @@ namespace fc { fc::raw::pack( s, variant(msg) ); } template - inline void unpack( Stream& s, fc::log_message& msg ) + inline void unpack( Stream& s, fc::log_message& msg, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); fc::variant vmsg; - fc::raw::unpack( s, vmsg ); + fc::raw::unpack( s, vmsg, depth ); msg = vmsg.as(); } @@ -68,10 +72,11 @@ namespace fc { } template - inline void unpack( Stream& s, fc::path& tp ) + inline void unpack( Stream& s, fc::path& tp, uint32_t depth ) { + depth++; std::string p; - fc::raw::unpack( s, p ); + fc::raw::unpack( s, p, depth ); tp = p; } @@ -83,7 +88,7 @@ namespace fc { } template - inline void unpack( Stream& s, fc::time_point_sec& tp ) + inline void unpack( Stream& s, fc::time_point_sec& tp, uint32_t ) { try { uint32_t sec; s.read( (char*)&sec, sizeof(sec) ); @@ -98,7 +103,7 @@ namespace fc { } template - inline void unpack( Stream& s, fc::time_point& tp ) + inline void unpack( Stream& s, fc::time_point& tp, uint32_t ) { try { uint64_t usec; s.read( (char*)&usec, sizeof(usec) ); @@ -113,7 +118,7 @@ namespace fc { } template - inline void unpack( Stream& s, fc::microseconds& usec ) + inline void unpack( Stream& s, fc::microseconds& usec, uint32_t ) { try { uint64_t usec_as_int64; s.read( (char*)&usec_as_int64, sizeof(usec_as_int64) ); @@ -127,7 +132,7 @@ namespace fc { } template - inline void unpack( Stream& s, fc::array& v) + inline void unpack( Stream& s, fc::array& v, uint32_t ) { try { s.read( (char*)&v.data[0], N*sizeof(T) ); } FC_RETHROW_EXCEPTIONS( warn, "fc::array", ("type",fc::get_typename::name())("length",N) ) } @@ -139,7 +144,7 @@ namespace fc { } template - inline void unpack( Stream& s, fc::int_array& v) + inline void unpack( Stream& s, fc::int_array& v, uint32_t ) { try { s.read( (char*)&v.data[0], N*sizeof(T) ); } FC_RETHROW_EXCEPTIONS( warn, "fc::int_array", ("type",fc::get_typename::name())("length",N) ) } @@ -151,10 +156,12 @@ namespace fc { } template - inline void unpack( Stream& s, std::shared_ptr& v) + inline void unpack( Stream& s, std::shared_ptr& v, uint32_t depth ) { try { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); v = std::make_shared(); - fc::raw::unpack( s, *v ); + fc::raw::unpack( s, *v, depth ); } FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr", ("type",fc::get_typename::name()) ) } template inline void pack( Stream& s, const signed_int& v ) { @@ -177,7 +184,7 @@ namespace fc { }while( val ); } - template inline void unpack( Stream& s, signed_int& vi ) { + template inline void unpack( Stream& s, signed_int& vi, uint32_t ) { uint32_t v = 0, by = 0, limit = 0; char b = 0; do { s.get(b); @@ -189,7 +196,7 @@ namespace fc { vi.value = v&0x01 ? vi.value : -vi.value; vi.value = -vi.value; } - template inline void unpack( Stream& s, unsigned_int& vi ) { + template inline void unpack( Stream& s, unsigned_int& vi, uint32_t ) { uint32_t v = 0, by = 0, limit = 0; char b = 0; do { s.get(b); @@ -200,10 +207,12 @@ namespace fc { vi.value = static_cast(v); } - template inline void unpack( Stream& s, const T& vi ) + template inline void unpack( Stream& s, const T& vi, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); T tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); FC_ASSERT( vi == tmp ); } @@ -213,7 +222,12 @@ namespace fc { void pack( Stream& s, const safe& v ) { fc::raw::pack( s, v.value ); } template - void unpack( Stream& s, fc::safe& v ) { fc::raw::unpack( s, v.value ); } + void unpack( Stream& s, fc::safe& v, uint32_t depth ) + { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + fc::raw::unpack( s, v.value, depth ); + } template void pack( Stream& s, const fc::fwd& v ) { @@ -221,14 +235,22 @@ namespace fc { } template - void unpack( Stream& s, fc::fwd& v ) { - fc::raw::unpack( *v ); + void unpack( Stream& s, fc::fwd& v, uint32_t depth ) + { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + fc::raw::unpack( *v, depth ); } template void pack( Stream& s, const fc::smart_ref& v ) { fc::raw::pack( s, *v ); } template - void unpack( Stream& s, fc::smart_ref& v ) { fc::raw::unpack( s, *v ); } + void unpack( Stream& s, fc::smart_ref& v, uint32_t depth ) + { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + fc::raw::unpack( s, *v, depth ); + } // optional template @@ -238,10 +260,12 @@ namespace fc { } template - void unpack( Stream& s, fc::optional& v ) + void unpack( Stream& s, fc::optional& v, uint32_t depth ) { try { - bool b; fc::raw::unpack( s, b ); - if( b ) { v = T(); fc::raw::unpack( s, *v ); } + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + bool b; fc::raw::unpack( s, b, depth ); + if( b ) { v = T(); fc::raw::unpack( s, *v, depth ); } } FC_RETHROW_EXCEPTIONS( warn, "optional<${type}>", ("type",fc::get_typename::name() ) ) } // std::vector @@ -250,8 +274,9 @@ namespace fc { if( value.size() ) s.write( &value.front(), (uint32_t)value.size() ); } - template inline void unpack( Stream& s, std::vector& value ) { - unsigned_int size; fc::raw::unpack( s, size ); + template inline void unpack( Stream& s, std::vector& value, uint32_t depth ) { + depth++; + unsigned_int size; fc::raw::unpack( s, size, depth ); FC_ASSERT( size.value < MAX_ARRAY_ALLOC_SIZE ); value.resize(size.value); if( value.size() ) @@ -264,9 +289,10 @@ namespace fc { if( v.size() ) s.write( v.c_str(), v.size() ); } - template inline void unpack( Stream& s, fc::string& v ) { + template inline void unpack( Stream& s, fc::string& v, uint32_t depth ) { + depth++; std::vector tmp; - fc::raw::unpack(s,tmp); + fc::raw::unpack(s,tmp,depth); if( tmp.size() ) v = fc::string(tmp.data(),tmp.data()+tmp.size()); else v = fc::string(); @@ -274,10 +300,11 @@ namespace fc { // bool template inline void pack( Stream& s, const bool& v ) { fc::raw::pack( s, uint8_t(v) ); } - template inline void unpack( Stream& s, bool& v ) + template inline void unpack( Stream& s, bool& v, uint32_t depth ) { + depth++; uint8_t b; - fc::raw::unpack( s, b ); + fc::raw::unpack( s, b, depth ); FC_ASSERT( (b & ~1) == 0 ); v=(b!=0); } @@ -318,7 +345,7 @@ namespace fc { template static inline void pack( Stream& s, const T& v ) { s << v; } template - static inline void unpack( Stream& s, T& v ) { s >> v; } + static inline void unpack( Stream& s, T& v, uint32_t depth = 0 ) { s >> v; } }; template<> @@ -328,7 +355,7 @@ namespace fc { s.write( (char*)&v, sizeof(v) ); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v, uint32_t ) { s.read( (char*)&v, sizeof(v) ); } }; @@ -340,7 +367,7 @@ namespace fc { fc::reflector::visit( pack_object_visitor( v, s ) ); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v, uint32_t ) { fc::reflector::visit( unpack_object_visitor( v, s ) ); } }; @@ -351,9 +378,11 @@ namespace fc { fc::raw::pack(s, (int64_t)v); } template - static inline void unpack( Stream& s, T& v ) { + static inline void unpack( Stream& s, T& v, uint32_t depth = 0 ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); int64_t temp; - fc::raw::unpack(s, temp); + fc::raw::unpack(s, temp, depth); v = (T)temp; } }; @@ -365,8 +394,10 @@ namespace fc { if_class::type>::pack(s,v); } template - static inline void unpack( Stream& s, T& v ) { - if_class::type>::unpack(s,v); + static inline void unpack( Stream& s, T& v, uint32_t depth = 0 ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + if_class::type>::unpack(s,v,depth); } }; template<> @@ -376,12 +407,14 @@ namespace fc { if_enum< typename fc::reflector::is_enum >::pack(s,v); } template - static inline void unpack( Stream& s, T& v ) { - if_enum< typename fc::reflector::is_enum >::unpack(s,v); + static inline void unpack( Stream& s, T& v, uint32_t depth = 0 ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + if_enum< typename fc::reflector::is_enum >::unpack(s,v,depth); } }; - } // namesapce detail + } // namespace detail template inline void pack( Stream& s, const std::unordered_set& value ) { @@ -394,15 +427,16 @@ namespace fc { } } template - inline void unpack( Stream& s, std::unordered_set& value ) { - unsigned_int size; fc::raw::unpack( s, size ); + inline void unpack( Stream& s, std::unordered_set& value, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + unsigned_int size; fc::raw::unpack( s, size, depth ); value.clear(); FC_ASSERT( size.value*sizeof(T) < MAX_ARRAY_ALLOC_SIZE ); - value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { T tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); value.insert( std::move(tmp) ); } } @@ -414,10 +448,12 @@ namespace fc { fc::raw::pack( s, value.second ); } template - inline void unpack( Stream& s, std::pair& value ) + inline void unpack( Stream& s, std::pair& value, uint32_t depth ) { - fc::raw::unpack( s, value.first ); - fc::raw::unpack( s, value.second ); + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + fc::raw::unpack( s, value.first, depth ); + fc::raw::unpack( s, value.second, depth ); } template @@ -431,16 +467,17 @@ namespace fc { } } template - inline void unpack( Stream& s, std::unordered_map& value ) + inline void unpack( Stream& s, std::unordered_map& value, uint32_t depth ) { - unsigned_int size; fc::raw::unpack( s, size ); + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + unsigned_int size; fc::raw::unpack( s, size, depth ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); - value.reserve(size.value); for( uint32_t i = 0; i < size.value; ++i ) { std::pair tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); value.insert( std::move(tmp) ); } } @@ -455,15 +492,17 @@ namespace fc { } } template - inline void unpack( Stream& s, std::map& value ) + inline void unpack( Stream& s, std::map& value, uint32_t depth ) { - unsigned_int size; fc::raw::unpack( s, size ); + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + unsigned_int size; fc::raw::unpack( s, size, depth ); value.clear(); FC_ASSERT( size.value*(sizeof(K)+sizeof(V)) < MAX_ARRAY_ALLOC_SIZE ); for( uint32_t i = 0; i < size.value; ++i ) { std::pair tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); value.insert( std::move(tmp) ); } } @@ -480,15 +519,16 @@ namespace fc { } template - inline void unpack( Stream& s, std::deque& value ) { - unsigned_int size; fc::raw::unpack( s, size ); + inline void unpack( Stream& s, std::deque& value, uint32_t depth ) { + depth++; + 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.resize(size.value); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::unpack( s, *itr ); - ++itr; + for ( size_t i = 0; i < size.value; i++ ) + { + T tmp; + fc::raw::unpack( s, tmp, depth ); + value.emplace_back( std::move( tmp ) ); } } @@ -504,15 +544,16 @@ namespace fc { } template - inline void unpack( Stream& s, std::vector& value ) { + inline void unpack( Stream& s, std::vector& value, uint32_t depth ) { + depth++; + 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.resize(size.value); - auto itr = value.begin(); - auto end = value.end(); - while( itr != end ) { - fc::raw::unpack( s, *itr ); - ++itr; + for ( size_t i = 0; i < size.value; i++ ) + { + T tmp; + fc::raw::unpack( s, tmp, depth ); + value.emplace_back( std::move( tmp ) ); } } @@ -528,12 +569,14 @@ namespace fc { } template - inline void unpack( Stream& s, std::set& value ) { - unsigned_int size; fc::raw::unpack( s, size ); + inline void unpack( Stream& s, std::set& value, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + unsigned_int size; fc::raw::unpack( s, size, depth ); for( uint64_t i = 0; i < size.value; ++i ) { typename std::set::value_type tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); value.insert( std::move(tmp) ); } } @@ -550,12 +593,14 @@ namespace fc { } template - inline void unpack( Stream& s, std::multiset& value ) { - unsigned_int size; fc::raw::unpack( s, size ); + inline void unpack( Stream& s, std::multiset& value, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + unsigned_int size; fc::raw::unpack( s, size, depth ); for( uint64_t i = 0; i < size.value; ++i ) { typename std::multiset::value_type tmp; - fc::raw::unpack( s, tmp ); + fc::raw::unpack( s, tmp, depth ); value.insert( std::move(tmp) ); } } @@ -567,9 +612,11 @@ namespace fc { fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::pack(s,v); } template - inline void unpack( Stream& s, T& v ) + inline void unpack( Stream& s, T& v, uint32_t depth ) { try { - fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack(s,v); + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); + fc::raw::detail::if_reflected< typename fc::reflector::is_defined >::unpack(s,v,depth); } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template @@ -595,22 +642,24 @@ namespace fc { } template - inline T unpack_from_vector( const std::vector& s ) + inline T unpack_from_vector( const std::vector& s, uint32_t depth ) { try { + depth++; T tmp; if( s.size() ) { datastream ds( s.data(), size_t(s.size()) ); - fc::raw::unpack(ds,tmp); + fc::raw::unpack(ds,tmp,depth); } return tmp; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline void unpack_from_vector( const std::vector& s, T& tmp ) + inline void unpack_from_vector( const std::vector& s, T& tmp, uint32_t depth = 0 ) { try { + depth++; if( s.size() ) { datastream ds( s.data(), size_t(s.size()) ); - fc::raw::unpack(ds,tmp); + fc::raw::unpack(ds,tmp,depth); } } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } @@ -621,19 +670,21 @@ namespace fc { } template - inline T unpack_from_char_array( const char* d, uint32_t s ) + inline T unpack_from_char_array( const char* d, uint32_t s, uint32_t depth ) { try { + depth++; T v; datastream ds( d, s ); - fc::raw::unpack(ds,v); + fc::raw::unpack(ds,v,depth); return v; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } template - inline void unpack_from_char_array( const char* d, uint32_t s, T& v ) + inline void unpack_from_char_array( const char* d, uint32_t s, T& v, uint32_t depth ) { try { + depth++; datastream ds( d, s ); - fc::raw::unpack(ds,v); + fc::raw::unpack(ds,v,depth); return v; } FC_RETHROW_EXCEPTIONS( warn, "error unpacking ${type}", ("type",fc::get_typename::name() ) ) } @@ -671,10 +722,12 @@ namespace fc { sv.visit( pack_static_variant(s) ); } - template void unpack( Stream& s, static_variant& sv ) + template void unpack( Stream& s, static_variant& sv, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int w; - fc::raw::unpack( s, w ); + fc::raw::unpack( s, w, depth ); sv.set_which(w.value); sv.visit( unpack_static_variant(s) ); } diff --git a/libraries/fc/include/fc/io/raw_fwd.hpp b/libraries/fc/include/fc/io/raw_fwd.hpp index 154d9ba79f..646219a516 100644 --- a/libraries/fc/include/fc/io/raw_fwd.hpp +++ b/libraries/fc/include/fc/io/raw_fwd.hpp @@ -12,6 +12,7 @@ #include #define MAX_ARRAY_ALLOC_SIZE (1024*1024*10) +#define MAX_RECURSION_DEPTH (20) namespace fc { class time_point; @@ -33,98 +34,96 @@ namespace fc { inline size_t pack_size( const T& v ); template inline void pack( Stream& s, const fc::fixed_string& u ); - template inline void unpack( Stream& s, fc::fixed_string& u ); + template inline void unpack( Stream& s, fc::fixed_string& u, uint32_t depth = 0 ); template inline void pack( Stream& s, const fc::enum_type& tp ); template - inline void unpack( Stream& s, fc::enum_type& tp ); + inline void unpack( Stream& s, fc::enum_type& tp, uint32_t depth = 0 ); template inline void pack( Stream& s, const std::set& value ); - template inline void unpack( Stream& s, std::set& value ); + template inline void unpack( Stream& s, std::set& value, uint32_t depth = 0 ); template inline void pack( Stream& s, const std::multiset& value ); - template inline void unpack( Stream& s, std::multiset& value ); + template inline void unpack( Stream& s, std::multiset& value, uint32_t depth = 0 ); template inline void pack( Stream& s, const std::unordered_set& value ); - template inline void unpack( Stream& s, std::unordered_set& value ); + template inline void unpack( Stream& s, std::unordered_set& value, uint32_t depth = 0 ); template void pack( Stream& s, const static_variant& sv ); - template void unpack( Stream& s, static_variant& sv ); - - template inline void pack( Stream& s, const flat_set& value ); - template inline void unpack( Stream& s, flat_set& value ); + 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 ); + 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 ); + template inline void unpack( Stream& s, std::unordered_map& value, uint32_t depth = 0 ); template inline void pack( Stream& s, const std::map& value ); - template inline void unpack( Stream& s, std::map& value ); - - template inline void pack( Stream& s, const flat_map& value ); - template inline void unpack( Stream& s, flat_map& value ); + template inline void unpack( Stream& s, std::map& value, uint32_t depth = 0 ); template inline void pack( Stream& s, const std::pair& value ); - template inline void unpack( Stream& s, std::pair& value ); + template inline void unpack( Stream& s, std::pair& value, uint32_t depth = 0 ); template inline void pack( Stream& s, const variant_object& v ); - template inline void unpack( Stream& s, variant_object& v ); + template inline void unpack( Stream& s, variant_object& v, uint32_t depth = 0 ); template inline void pack( Stream& s, const variant& v ); - template inline void unpack( Stream& s, variant& v ); + template inline void unpack( Stream& s, variant& v, uint32_t depth = 0 ); template inline void pack( Stream& s, const path& v ); - template inline void unpack( Stream& s, path& v ); + template inline void unpack( Stream& s, path& v, uint32_t depth = 0 ); template inline void pack( Stream& s, const ip::endpoint& v ); - template inline void unpack( Stream& s, ip::endpoint& v ); + template inline void unpack( Stream& s, ip::endpoint& v, uint32_t depth = 0 ); + template inline void pack( Stream& s, const ip::address& v ); + template inline void unpack( Stream& s, ip::address& v, uint32_t depth = 0 ); - template void unpack( Stream& s, fc::optional& v ); - template void unpack( Stream& s, const T& v ); + template void unpack( Stream& s, fc::optional& v, uint32_t depth = 0 ); + template void unpack( Stream& s, const T& v, uint32_t depth = 0 ); template void pack( Stream& s, const fc::optional& v ); template void pack( Stream& s, const safe& v ); - template void unpack( Stream& s, fc::safe& v ); + template void unpack( Stream& s, fc::safe& v, uint32_t depth = 0 ); - template void unpack( Stream& s, time_point& ); + template void unpack( Stream& s, microseconds&, uint32_t depth = 0 ); + template void pack( Stream& s, const microseconds& ); + template void unpack( Stream& s, time_point&, uint32_t depth = 0 ); template void pack( Stream& s, const time_point& ); - template void unpack( Stream& s, time_point_sec& ); + template void unpack( Stream& s, time_point_sec&, uint32_t depth = 0 ); template void pack( Stream& s, const time_point_sec& ); - template void unpack( Stream& s, std::string& ); + template void unpack( Stream& s, std::string&, uint32_t depth = 0 ); template void pack( Stream& s, const std::string& ); - template void unpack( Stream& s, fc::ecc::public_key& ); + template void unpack( Stream& s, fc::ecc::public_key&, uint32_t depth = 0 ); template void pack( Stream& s, const fc::ecc::public_key& ); - template void unpack( Stream& s, fc::ecc::private_key& ); + template void unpack( Stream& s, fc::ecc::private_key&, uint32_t depth = 0 ); template void pack( Stream& s, const fc::ecc::private_key& ); template inline void pack( Stream& s, const T& v ); - template inline void unpack( Stream& s, T& v ); + template inline void unpack( Stream& s, T& v, uint32_t depth = 0 ); template inline void pack( Stream& s, const std::vector& v ); - template inline void unpack( Stream& s, std::vector& v ); + template inline void unpack( Stream& s, std::vector& v, uint32_t depth = 0 ); template inline void pack( Stream& s, const signed_int& v ); - template inline void unpack( Stream& s, signed_int& vi ); + template inline void unpack( Stream& s, signed_int& vi, uint32_t depth = 0 ); template inline void pack( Stream& s, const unsigned_int& v ); - template inline void unpack( Stream& s, unsigned_int& vi ); + template inline void unpack( Stream& s, unsigned_int& vi, uint32_t depth = 0 ); template inline void pack( Stream& s, const char* v ); template inline void pack( Stream& s, const std::vector& value ); - template inline void unpack( Stream& s, std::vector& value ); + template inline void unpack( Stream& s, std::vector& value, uint32_t depth = 0 ); template inline void pack( Stream& s, const fc::array& v); - template inline void unpack( Stream& s, fc::array& v); + template inline void unpack( Stream& s, fc::array& v, uint32_t depth = 0); template inline void pack( Stream& s, const fc::int_array& v); - template inline void unpack( Stream& s, fc::int_array& v); + template inline void unpack( Stream& s, fc::int_array& v, uint32_t depth = 0); template inline void pack( Stream& s, const bool& v ); - template inline void unpack( Stream& s, bool& v ); + template inline void unpack( Stream& s, bool& v, uint32_t depth = 0 ); template inline std::vector pack_to_vector( const T& v ); - template inline T unpack_from_vector( const std::vector& s ); - template inline T unpack_from_char_array( const char* d, uint32_t s ); - template inline void unpack_from_char_array( const char* d, uint32_t s, T& v ); + template inline T unpack_from_vector( const std::vector& s, uint32_t depth = 0 ); + template inline T unpack_from_char_array( const char* d, uint32_t s, uint32_t depth = 0 ); + template inline void unpack_from_char_array( const char* d, uint32_t s, T& v, 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 24fe3f6e36..53b8898539 100644 --- a/libraries/fc/include/fc/io/raw_variant.hpp +++ b/libraries/fc/include/fc/io/raw_variant.hpp @@ -53,10 +53,12 @@ namespace fc { namespace raw { v.visit( variant_packer(s) ); } template - inline void unpack( Stream& s, variant& v ) + inline void unpack( Stream& s, variant& v, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); uint8_t t; - unpack( s, t ); + unpack( s, t, depth ); switch( t ) { case variant::null_type: @@ -64,49 +66,49 @@ namespace fc { namespace raw { case variant::int64_type: { int64_t val; - raw::unpack(s,val); + raw::unpack(s,val,depth); v = val; return; } case variant::uint64_type: { uint64_t val; - raw::unpack(s,val); + raw::unpack(s,val,depth); v = val; return; } case variant::double_type: { double val; - raw::unpack(s,val); + raw::unpack(s,val,depth); v = val; return; } case variant::bool_type: { bool val; - raw::unpack(s,val); + raw::unpack(s,val,depth); v = val; return; } case variant::string_type: { fc::string val; - raw::unpack(s,val); + raw::unpack(s,val,depth); v = fc::move(val); return; } case variant::array_type: { variants val; - raw::unpack(s,val); + raw::unpack(s,val,depth); v = fc::move(val); return; } case variant::object_type: { variant_object val; - raw::unpack(s,val); + raw::unpack(s,val,depth); v = fc::move(val); return; } @@ -127,10 +129,12 @@ namespace fc { namespace raw { } } template - inline void unpack( Stream& s, variant_object& v ) + inline void unpack( Stream& s, variant_object& v, uint32_t depth ) { + depth++; + FC_ASSERT( depth <= MAX_RECURSION_DEPTH ); unsigned_int vs; - unpack( s, vs ); + unpack( s, vs, depth ); mutable_variant_object mvo; mvo.reserve(vs.value); @@ -138,8 +142,8 @@ namespace fc { namespace raw { { fc::string key; fc::variant value; - fc::raw::unpack(s,key); - fc::raw::unpack(s,value); + fc::raw::unpack(s,key,depth); + fc::raw::unpack(s,value,depth); mvo.set( fc::move(key), fc::move(value) ); } v = fc::move(mvo); diff --git a/libraries/fc/include/fc/network/ip.hpp b/libraries/fc/include/fc/network/ip.hpp index 43fc5a442c..41f772f167 100644 --- a/libraries/fc/include/fc/network/ip.hpp +++ b/libraries/fc/include/fc/network/ip.hpp @@ -88,10 +88,11 @@ namespace fc { fc::raw::pack( s, uint32_t(v) ); } template - inline void unpack( Stream& s, ip::address& v ) + inline void unpack( Stream& s, ip::address& v, uint32_t depth ) { + depth++; uint32_t _ip; - fc::raw::unpack( s, _ip ); + fc::raw::unpack( s, _ip, depth ); v = ip::address(_ip); } @@ -102,12 +103,13 @@ namespace fc { fc::raw::pack( s, v.port() ); } template - inline void unpack( Stream& s, ip::endpoint& v ) + inline void unpack( Stream& s, ip::endpoint& v, uint32_t depth ) { + depth++; ip::address a; uint16_t p; - fc::raw::unpack( s, a ); - fc::raw::unpack( s, p ); + fc::raw::unpack( s, a, depth ); + fc::raw::unpack( s, p, depth ); v = ip::endpoint(a,p); } diff --git a/libraries/fc/include/fc/real128.hpp b/libraries/fc/include/fc/real128.hpp index 3a7d26dbef..4dd528e8c8 100644 --- a/libraries/fc/include/fc/real128.hpp +++ b/libraries/fc/include/fc/real128.hpp @@ -44,7 +44,7 @@ namespace fc { template inline void pack( Stream& s, const real128& value_to_pack ) { s.write( (char*)&value_to_pack, sizeof(value_to_pack) ); } template - inline void unpack( Stream& s, real128& value_to_unpack ) { s.read( (char*)&value_to_unpack, sizeof(value_to_unpack) ); } + inline void unpack( Stream& s, real128& value_to_unpack, uint32_t ) { s.read( (char*)&value_to_unpack, sizeof(value_to_unpack) ); } } diff --git a/libraries/fc/include/fc/uint128.hpp b/libraries/fc/include/fc/uint128.hpp index 7d4394bf03..98432cd69a 100644 --- a/libraries/fc/include/fc/uint128.hpp +++ b/libraries/fc/include/fc/uint128.hpp @@ -134,7 +134,7 @@ namespace fc template inline void pack( Stream& s, const uint128& u ) { s.write( (char*)&u, sizeof(u) ); } template - inline void unpack( Stream& s, uint128& u ) { s.read( (char*)&u, sizeof(u) ); } + inline void unpack( Stream& s, uint128& u, uint32_t ) { s.read( (char*)&u, sizeof(u) ); } } size_t city_hash_size_t(const char *buf, size_t len); diff --git a/libraries/protocol/include/steem/protocol/asset_symbol.hpp b/libraries/protocol/include/steem/protocol/asset_symbol.hpp index 244600b950..a8b9881ca3 100644 --- a/libraries/protocol/include/steem/protocol/asset_symbol.hpp +++ b/libraries/protocol/include/steem/protocol/asset_symbol.hpp @@ -173,7 +173,7 @@ inline void pack( Stream& s, const steem::protocol::asset_symbol_type& sym ) } template< typename Stream > -inline void unpack( Stream& s, steem::protocol::asset_symbol_type& sym ) +inline void unpack( Stream& s, steem::protocol::asset_symbol_type& sym, uint32_t ) { uint64_t ser = 0; s.read( (char*) &ser, 4 ); diff --git a/libraries/protocol/include/steem/protocol/fixed_string.hpp b/libraries/protocol/include/steem/protocol/fixed_string.hpp index 669c4ffe71..ca1c536842 100644 --- a/libraries/protocol/include/steem/protocol/fixed_string.hpp +++ b/libraries/protocol/include/steem/protocol/fixed_string.hpp @@ -197,10 +197,11 @@ inline void pack( Stream& s, const steem::protocol::fixed_string_impl< Storage > } template< typename Stream, typename Storage > -inline void unpack( Stream& s, steem::protocol::fixed_string_impl< Storage >& u ) +inline void unpack( Stream& s, steem::protocol::fixed_string_impl< Storage >& u, uint32_t depth ) { + depth++; std::string str; - unpack( s, str ); + unpack( s, str, depth ); u = str; } diff --git a/libraries/protocol/include/steem/protocol/legacy_asset.hpp b/libraries/protocol/include/steem/protocol/legacy_asset.hpp index 33da29ac15..37de5071f0 100644 --- a/libraries/protocol/include/steem/protocol/legacy_asset.hpp +++ b/libraries/protocol/include/steem/protocol/legacy_asset.hpp @@ -77,7 +77,7 @@ inline void pack( Stream& s, const steem::protocol::legacy_steem_asset_symbol_ty } template< typename Stream > -inline void unpack( Stream& s, steem::protocol::legacy_steem_asset_symbol_type& sym ) +inline void unpack( Stream& s, steem::protocol::legacy_steem_asset_symbol_type& sym, uint32_t depth ) { // 994240: "account_creation_fee": "0.1 STEEM" // 1021529: "account_creation_fee": "10.0 STEEM" @@ -87,10 +87,10 @@ inline void unpack( Stream& s, steem::protocol::legacy_steem_asset_symbol_type& // 4338089: "account_creation_fee": "0.001 0.001" // 4626205: "account_creation_fee": "6.000 6.000" // 4632595: "account_creation_fee": "6.000 6.000" - + depth++; uint64_t ser = 0; - fc::raw::unpack( s, ser ); + fc::raw::unpack( s, ser, depth ); switch( ser ) { case STEEM_SYMBOL_LEGACY_SER_1: diff --git a/libraries/protocol/include/steem/protocol/types_fwd.hpp b/libraries/protocol/include/steem/protocol/types_fwd.hpp index 0c23036b8b..851d7547ea 100644 --- a/libraries/protocol/include/steem/protocol/types_fwd.hpp +++ b/libraries/protocol/include/steem/protocol/types_fwd.hpp @@ -1,7 +1,8 @@ #pragma once +#include +#include namespace fc { -class uint128; class variant; } // fc @@ -16,25 +17,20 @@ struct legacy_steem_asset; namespace fc { namespace raw { -template -inline void pack( Stream& s, const uint128& u ); -template -inline void unpack( Stream& s, uint128& u ); - template< typename Stream, typename Storage > inline void pack( Stream& s, const steem::protocol::fixed_string_impl< Storage >& u ); template< typename Stream, typename Storage > -inline void unpack( Stream& s, steem::protocol::fixed_string_impl< Storage >& u ); +inline void unpack( Stream& s, steem::protocol::fixed_string_impl< Storage >& u, uint32_t depth = 0 ); template< typename Stream > inline void pack( Stream& s, const steem::protocol::asset_symbol_type& sym ); template< typename Stream > -inline void unpack( Stream& s, steem::protocol::asset_symbol_type& sym ); +inline void unpack( Stream& s, steem::protocol::asset_symbol_type& sym, uint32_t depth = 0 ); template< typename Stream > inline void pack( Stream& s, const steem::protocol::legacy_steem_asset_symbol_type& sym ); template< typename Stream > -inline void unpack( Stream& s, steem::protocol::legacy_steem_asset_symbol_type& sym ); +inline void unpack( Stream& s, steem::protocol::legacy_steem_asset_symbol_type& sym, uint32_t depth = 0 ); } // raw