From f8940a686a809eefb9424b2428a149879cf947ae Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 18 Jul 2018 17:55:46 +0200 Subject: [PATCH 01/10] Added unit test for serialization/deserialization of unsigned_int --- tests/CMakeLists.txt | 1 + tests/io/varint_tests.cpp | 53 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 tests/io/varint_tests.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 153067e..600f6f8 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -49,6 +49,7 @@ add_executable( all_tests all_tests.cpp io/json_tests.cpp io/stream_tests.cpp io/tcp_test.cpp + io/varint_tests.cpp network/http/websocket_test.cpp thread/task_cancel.cpp thread/thread_tests.cpp diff --git a/tests/io/varint_tests.cpp b/tests/io/varint_tests.cpp new file mode 100644 index 0000000..4309d0f --- /dev/null +++ b/tests/io/varint_tests.cpp @@ -0,0 +1,53 @@ +#include + +#include +#include +#include + +BOOST_AUTO_TEST_SUITE(varint_tests) + +#define UINT_LENGTH (1 + 1 + 1 + 1 + 1 + 1 + 2 + 2 + 2 + 3 + 3 + 3 + 4 + 4 + 4 + 5 + 5) +static const std::string EXPECTED_UINTS( "\020" // 16 = length of array + "\0\1\2\020\177\200\1\200\2\377\177" + "\200\200\1\200\200\2\377\377\177" + "\200\200\200\1\200\200\200\2" + "\377\377\377\177\200\200\200\200\1" + "\252\325\252\325\012", UINT_LENGTH ); +static const std::vector TEST_U = { + 0, // \0 + 1, // \1 + 2, // \2 + 0x10, // \020 + 0x7f, // \177 + 0x80, // \200\1 + 0x100, // \200\2 + 0x3fff, // \377\177 + 0x4000, // \200\200\1 + 0x8000, // \200\200\2 + 0x1fffff, // \377\377\177 + 0x200000, // \200\200\200\1 + 0x400000, // \200\200\200\2 + 0xfffffff, // \377\377\377\177 + 0x10000000, // \200\200\200\200\1 + 0xaaaaaaaa // \252\325\252\325\012 + }; +BOOST_AUTO_TEST_CASE( test_unsigned ) +{ + const std::vector packed_u = fc::raw::pack>( TEST_U, 3 ); + BOOST_CHECK_EQUAL( UINT_LENGTH, packed_u.size() ); + BOOST_CHECK_EQUAL( EXPECTED_UINTS, std::string( packed_u.data(), packed_u.size() ) ); + std::vector unpacked_u; + fc::raw::unpack>( packed_u, unpacked_u, 3 ); + BOOST_CHECK_EQUAL( TEST_U.size(), unpacked_u.size() ); + for( size_t i = 0; i < TEST_U.size(); i++ ) + BOOST_CHECK_EQUAL( TEST_U[i].value, unpacked_u[i].value ); + + const std::string json_u = fc::json::to_string(fc::variant( TEST_U, 3 )); + BOOST_CHECK_EQUAL( "[0,1,2,16,127,128,256,16383,16384,32768,2097151,2097152,4194304,268435455,268435456,2863311530]", json_u ); + std::vector unjson_u = fc::json::from_string( json_u ).as>( 3 ); + BOOST_CHECK_EQUAL( TEST_U.size(), unjson_u.size() ); + for( size_t i = 0; i < TEST_U.size(); i++ ) + BOOST_CHECK_EQUAL( TEST_U[i].value, unjson_u[i].value ); +} + +BOOST_AUTO_TEST_SUITE_END() From 9483935d6446657ffc1c8d329307e08f2eb1ab05 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Wed, 18 Jul 2018 18:13:48 +0200 Subject: [PATCH 02/10] Support 64 bit values in unsigned_int object --- include/fc/container/flat.hpp | 6 +++--- include/fc/interprocess/container.hpp | 2 +- include/fc/io/raw.hpp | 18 +++++++++--------- include/fc/io/raw_variant.hpp | 2 +- include/fc/io/varint.hpp | 27 ++++++++++++--------------- src/io/varint.cpp | 2 +- 6 files changed, 27 insertions(+), 30 deletions(-) diff --git a/include/fc/container/flat.hpp b/include/fc/container/flat.hpp index 2eca459..5e6a363 100644 --- a/include/fc/container/flat.hpp +++ b/include/fc/container/flat.hpp @@ -11,7 +11,7 @@ namespace fc { inline void pack( Stream& s, const flat_set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -38,7 +38,7 @@ namespace fc { inline void pack( Stream& s, const flat_map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -67,7 +67,7 @@ namespace fc { void pack( Stream& s, const bip::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + pack( s, unsigned_int(value.size()), _max_depth ); if( !std::is_fundamental::value ) { auto itr = value.begin(); auto end = value.end(); diff --git a/include/fc/interprocess/container.hpp b/include/fc/interprocess/container.hpp index 7ede74b..a00346e 100644 --- a/include/fc/interprocess/container.hpp +++ b/include/fc/interprocess/container.hpp @@ -113,7 +113,7 @@ namespace fc { inline void pack( Stream& s, const bip::vector& value, uint32_t _max_depth=FC_PACK_MAX_DEPTH ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 9ef61ec..c7035ec 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -273,9 +273,9 @@ namespace fc { // std::vector template inline void pack( Stream& s, const std::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth - 1 ); + fc::raw::pack( s, unsigned_int(value.size()), _max_depth - 1 ); if( value.size() ) - s.write( &value.front(), (uint32_t)value.size() ); + s.write( &value.front(), value.size() ); } template inline void unpack( Stream& s, std::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); @@ -289,7 +289,7 @@ namespace fc { // fc::string template inline void pack( Stream& s, const fc::string& v, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); - fc::raw::pack( s, unsigned_int((uint32_t)v.size()), _max_depth - 1 ); + fc::raw::pack( s, unsigned_int(v.size()), _max_depth - 1 ); if( v.size() ) s.write( v.c_str(), v.size() ); } @@ -433,7 +433,7 @@ namespace fc { inline void pack( Stream& s, const std::unordered_set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + fc::raw::pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -478,7 +478,7 @@ namespace fc { inline void pack( Stream& s, const std::unordered_map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + fc::raw::pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -506,7 +506,7 @@ namespace fc { inline void pack( Stream& s, const std::map& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + fc::raw::pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -534,7 +534,7 @@ namespace fc { inline void pack( Stream& s, const std::deque& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + fc::raw::pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -562,7 +562,7 @@ namespace fc { inline void pack( Stream& s, const std::vector& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + fc::raw::pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { @@ -590,7 +590,7 @@ namespace fc { inline void pack( Stream& s, const std::set& value, uint32_t _max_depth ) { FC_ASSERT( _max_depth > 0 ); --_max_depth; - fc::raw::pack( s, unsigned_int((uint32_t)value.size()), _max_depth ); + fc::raw::pack( s, unsigned_int(value.size()), _max_depth ); auto itr = value.begin(); auto end = value.end(); while( itr != end ) { diff --git a/include/fc/io/raw_variant.hpp b/include/fc/io/raw_variant.hpp index b07fbaa..59b93d9 100644 --- a/include/fc/io/raw_variant.hpp +++ b/include/fc/io/raw_variant.hpp @@ -128,7 +128,7 @@ namespace fc { namespace raw { { FC_ASSERT( _max_depth > 0 ); --_max_depth; - unsigned_int vs = (uint32_t)v.size(); + unsigned_int vs = v.size(); pack( s, vs, _max_depth ); for( auto itr = v.begin(); itr != v.end(); ++itr ) { diff --git a/include/fc/io/varint.hpp b/include/fc/io/varint.hpp index 00a8023..80082f2 100644 --- a/include/fc/io/varint.hpp +++ b/include/fc/io/varint.hpp @@ -4,35 +4,32 @@ namespace fc { struct unsigned_int { - unsigned_int( uint32_t v = 0 ):value(v){} + unsigned_int( uint64_t v = 0 ):value(v){} template unsigned_int( T v ):value(v){} - //operator uint32_t()const { return value; } - //operator uint64_t()const { return value; } - template operator T()const { return static_cast(value); } - unsigned_int& operator=( int32_t v ) { value = v; return *this; } + unsigned_int& operator=( uint64_t v ) { value = v; return *this; } - uint32_t value; + uint64_t value; - friend bool operator==( const unsigned_int& i, const uint32_t& v ) { return i.value == v; } - friend bool operator==( const uint32_t& i, const unsigned_int& v ) { return i == v.value; } + friend bool operator==( const unsigned_int& i, const uint64_t& v ) { return i.value == v; } + friend bool operator==( const uint64_t& i, const unsigned_int& v ) { return i == v.value; } friend bool operator==( const unsigned_int& i, const unsigned_int& v ) { return i.value == v.value; } - friend bool operator!=( const unsigned_int& i, const uint32_t& v ) { return i.value != v; } - friend bool operator!=( const uint32_t& i, const unsigned_int& v ) { return i != v.value; } + friend bool operator!=( const unsigned_int& i, const uint64_t& v ) { return i.value != v; } + friend bool operator!=( const uint64_t& i, const unsigned_int& v ) { return i != v.value; } friend bool operator!=( const unsigned_int& i, const unsigned_int& v ) { return i.value != v.value; } - friend bool operator<( const unsigned_int& i, const uint32_t& v ) { return i.value < v; } - friend bool operator<( const uint32_t& i, const unsigned_int& v ) { return i < v.value; } + friend bool operator<( const unsigned_int& i, const uint64_t& v ) { return i.value < v; } + friend bool operator<( const uint64_t& i, const unsigned_int& v ) { return i < v.value; } friend bool operator<( const unsigned_int& i, const unsigned_int& v ) { return i.value < v.value; } - friend bool operator>=( const unsigned_int& i, const uint32_t& v ) { return i.value >= v; } - friend bool operator>=( const uint32_t& i, const unsigned_int& v ) { return i >= v.value; } + friend bool operator>=( const unsigned_int& i, const uint64_t& v ) { return i.value >= v; } + friend bool operator>=( const uint64_t& i, const unsigned_int& v ) { return i >= v.value; } friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return i.value >= v.value; } }; @@ -95,7 +92,7 @@ namespace std public: size_t operator()(const fc::signed_int &a) const { - return std::hash()(a.value); + return std::hash()(a.value); } }; } diff --git a/src/io/varint.cpp b/src/io/varint.cpp index 6d5df6c..6384eec 100644 --- a/src/io/varint.cpp +++ b/src/io/varint.cpp @@ -6,5 +6,5 @@ namespace fc void to_variant( const signed_int& var, variant& vo, uint32_t max_depth ) { vo = var.value; } void from_variant( const variant& var, signed_int& vo, uint32_t max_depth ) { vo.value = static_cast(var.as_int64()); } void to_variant( const unsigned_int& var, variant& vo, uint32_t max_depth ) { vo = var.value; } -void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth ) { vo.value = static_cast(var.as_uint64()); } +void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth ) { vo.value = var.as_uint64(); } } From 58ac6ae20812deb5acc77d1546665fd3b00c2d60 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 18 Aug 2018 21:13:32 +0200 Subject: [PATCH 03/10] Changed some casts to uint64_t --- include/fc/io/raw.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index c7035ec..8bd0163 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -193,10 +193,10 @@ namespace fc { uint64_t v = 0; char b = 0; uint8_t by = 0; do { s.get(b); - v |= uint32_t(uint8_t(b) & 0x7f) << by; + v |= uint64_t(uint8_t(b) & 0x7f) << by; by += 7; } while( uint8_t(b) & 0x80 ); - vi.value = static_cast(v); + vi.value = static_cast(v); } template inline void unpack( Stream& s, const T& vi, uint32_t _max_depth ) From 72bcc8a926f518a1dfba4255ec2bee196d53fde0 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 18 Aug 2018 21:24:58 +0200 Subject: [PATCH 04/10] Fix #993 - limit unpacking length of signed_int and unsigned_int --- include/fc/io/raw.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 8bd0163..e254cd3 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -184,7 +184,7 @@ namespace fc { s.get(b); v |= uint32_t(uint8_t(b) & 0x7f) << by; by += 7; - } while( uint8_t(b) & 0x80 ); + } while( (uint8_t(b) & 0x80) && by < 32 ); vi.value = ((v>>1) ^ (v>>31)) + (v&0x01); vi.value = v&0x01 ? vi.value : -vi.value; vi.value = -vi.value; @@ -195,7 +195,7 @@ namespace fc { s.get(b); v |= uint64_t(uint8_t(b) & 0x7f) << by; by += 7; - } while( uint8_t(b) & 0x80 ); + } while( (uint8_t(b) & 0x80) && by < 64 ); vi.value = static_cast(v); } From a39e0d1a8ffedf00713af0319218d3321be893da Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sat, 18 Aug 2018 22:16:36 +0200 Subject: [PATCH 05/10] Expanded tests for unsigned_int to 64 bits --- tests/io/varint_tests.cpp | 51 +++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/tests/io/varint_tests.cpp b/tests/io/varint_tests.cpp index 4309d0f..e7b606f 100644 --- a/tests/io/varint_tests.cpp +++ b/tests/io/varint_tests.cpp @@ -6,13 +6,29 @@ BOOST_AUTO_TEST_SUITE(varint_tests) -#define UINT_LENGTH (1 + 1 + 1 + 1 + 1 + 1 + 2 + 2 + 2 + 3 + 3 + 3 + 4 + 4 + 4 + 5 + 5) -static const std::string EXPECTED_UINTS( "\020" // 16 = length of array - "\0\1\2\020\177\200\1\200\2\377\177" +#define UINT_LENGTH (1 + 5*1 + 3*2 + 3*3 + 3*4 + 2*5 + 3*6 + 3*7 + 3*8 + 3*9 + 2*10) +static const std::string EXPECTED_UINTS( "\036" // 30 = length of array + "\0\1\2\020\177" + "\200\1\200\2\377\177" "\200\200\1\200\200\2\377\377\177" - "\200\200\200\1\200\200\200\2" - "\377\377\377\177\200\200\200\200\1" - "\252\325\252\325\012", UINT_LENGTH ); + "\200\200\200\1\200\200\200\2\377\377\377\177" + "\200\200\200\200\1" + "\252\325\252\325\012" + "\200\200\200\200\200\1" + "\200\200\200\200\200\2" + "\377\377\377\377\377\177" + "\200\200\200\200\200\200\1" + "\200\200\200\200\200\200\2" + "\377\377\377\377\377\377\177" + "\200\200\200\200\200\200\200\1" + "\200\200\200\200\200\200\200\2" + "\377\377\377\377\377\377\377\177" + "\200\200\200\200\200\200\200\200\1" + "\200\200\200\200\200\200\200\200\2" + "\377\377\377\377\377\377\377\377\177" + "\200\200\200\200\200\200\200\200\200\1" + "\377\377\377\377\377\377\377\377\377\1", + UINT_LENGTH ); static const std::vector TEST_U = { 0, // \0 1, // \1 @@ -29,7 +45,21 @@ static const std::vector TEST_U = { 0x400000, // \200\200\200\2 0xfffffff, // \377\377\377\177 0x10000000, // \200\200\200\200\1 - 0xaaaaaaaa // \252\325\252\325\012 + 0xaaaaaaaa, // \252\325\252\325\012 + 0x800000000ULL, // \200\200\200\200\200\1 + 0x1000000000ULL, // \200\200\200\200\200\2 + 0x3ffffffffffULL, // \377\377\377\377\377\177 + 0x40000000000ULL, // \200\200\200\200\200\200\1 + 0x80000000000ULL, // \200\200\200\200\200\200\2 + 0x1ffffffffffffULL, // \377\377\377\377\377\377\177 + 0x2000000000000ULL, // \200\200\200\200\200\200\200\1 + 0x4000000000000ULL, // \200\200\200\200\200\200\200\2 + 0xffffffffffffffULL, // \377\377\377\377\377\377\377\177 + 0x100000000000000ULL, // \200\200\200\200\200\200\200\200\1 + 0x200000000000000ULL, // \200\200\200\200\200\200\200\200\2 + 0x7fffffffffffffffULL, // \377\377\377\377\377\377\377\377\177 + 0x8000000000000000ULL, // \200\200\200\200\200\200\200\200\200\1 + 0xffffffffffffffffULL // \377\377\377\377\377\377\377\377\377\1 }; BOOST_AUTO_TEST_CASE( test_unsigned ) { @@ -43,7 +73,12 @@ BOOST_AUTO_TEST_CASE( test_unsigned ) BOOST_CHECK_EQUAL( TEST_U[i].value, unpacked_u[i].value ); const std::string json_u = fc::json::to_string(fc::variant( TEST_U, 3 )); - BOOST_CHECK_EQUAL( "[0,1,2,16,127,128,256,16383,16384,32768,2097151,2097152,4194304,268435455,268435456,2863311530]", json_u ); + BOOST_CHECK_EQUAL( "[0,1,2,16,127,128,256,16383,16384,32768,2097151,2097152,4194304,268435455,268435456,2863311530," + "\"34359738368\",\"68719476736\",\"4398046511103\",\"4398046511104\"," + "\"8796093022208\",\"562949953421311\",\"562949953421312\"," + "\"1125899906842624\",\"72057594037927935\",\"72057594037927936\"," + "\"144115188075855872\",\"9223372036854775807\",\"9223372036854775808\"," + "\"18446744073709551615\"]", json_u ); std::vector unjson_u = fc::json::from_string( json_u ).as>( 3 ); BOOST_CHECK_EQUAL( TEST_U.size(), unjson_u.size() ); for( size_t i = 0; i < TEST_U.size(); i++ ) From 0c22469090a376352fec748362451d90ff27d73a Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 19 Aug 2018 10:26:52 +0200 Subject: [PATCH 06/10] #993 - unit test --- tests/io/varint_tests.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/io/varint_tests.cpp b/tests/io/varint_tests.cpp index e7b606f..ea0ef58 100644 --- a/tests/io/varint_tests.cpp +++ b/tests/io/varint_tests.cpp @@ -85,4 +85,40 @@ BOOST_AUTO_TEST_CASE( test_unsigned ) BOOST_CHECK_EQUAL( TEST_U[i].value, unjson_u[i].value ); } +BOOST_AUTO_TEST_CASE( test_limits ) +{ try { + static const std::string PACKED_U = "\04" + "\200\1" + "\200\200\200\200\200\200\200\200\100" + "\200\200\200\200\200\200\200\200\200\201" // not terminated + "\200\200\200\200\200\200\200\200\300\201"; // not terminated + std::vector unpacked_u; + fc::raw::unpack( std::vector( PACKED_U.begin(), PACKED_U.end() ), unpacked_u, 3 ); + BOOST_REQUIRE_EQUAL( 4, unpacked_u.size() ); + BOOST_CHECK_EQUAL( 0x80, unpacked_u[0].value ); + BOOST_CHECK_EQUAL( 0x4000000000000000ULL, unpacked_u[1].value ); + BOOST_CHECK_EQUAL( 0x8000000000000000ULL, unpacked_u[2].value ); + BOOST_CHECK_EQUAL( 0xc000000000000000ULL, unpacked_u[3].value ); + + /* Hm, seems that signed_int is broken, see below + static const std::string PACKED_S = "\04" + "\200\1" + "\200\200\200\200\04" + "\200\200\200\200\210" // not terminated + "\200\200\200\200\214"; // not terminated + std::vector unpacked_s; + fc::raw::unpack( std::vector( PACKED_S.begin(), PACKED_S.end() ), unpacked_s, 3 ); + BOOST_REQUIRE_EQUAL( 4, unpacked_s.size() ); + BOOST_CHECK_EQUAL( 0x40, unpacked_s[0].value ); + BOOST_CHECK_EQUAL( 0x20000000, unpacked_s[1].value ); + BOOST_CHECK_EQUAL( 0x40000000, unpacked_s[2].value ); + BOOST_CHECK_EQUAL( 0x60000000, unpacked_s[3].value ); + */ + + std::vector packed_s = fc::raw::pack( fc::signed_int(0x40000000), 3 ); + fc::signed_int tmp = fc::raw::unpack( packed_s, 3 ); + BOOST_CHECK_EQUAL( 0x40000000, tmp.value ); + +} FC_LOG_AND_RETHROW() } + BOOST_AUTO_TEST_SUITE_END() From 4b61f3ca3dba952a982f9d6102acc8956e33f54d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 19 Aug 2018 10:42:27 +0200 Subject: [PATCH 07/10] Fixed alleged c&p bug --- include/fc/io/varint.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/io/varint.hpp b/include/fc/io/varint.hpp index 80082f2..fe8e82e 100644 --- a/include/fc/io/varint.hpp +++ b/include/fc/io/varint.hpp @@ -90,7 +90,7 @@ namespace std struct hash { public: - size_t operator()(const fc::signed_int &a) const + size_t operator()(const fc::unsigned_int &a) const { return std::hash()(a.value); } From 1dcacbafc9e85552e8bd9b8b5082e1ce3364fe43 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 19 Aug 2018 18:26:46 +0200 Subject: [PATCH 08/10] Removed signed_int --- include/fc/io/raw.hpp | 21 ---------------- include/fc/io/raw_fwd.hpp | 3 --- include/fc/io/varint.hpp | 43 --------------------------------- include/fc/reflect/typename.hpp | 2 -- src/io/varint.cpp | 2 -- tests/io/varint_tests.cpp | 20 --------------- 6 files changed, 91 deletions(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index e254cd3..48811c2 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -158,16 +158,6 @@ namespace fc { fc::raw::unpack( s, *v, _max_depth - 1 ); } FC_RETHROW_EXCEPTIONS( warn, "std::shared_ptr", ("type",fc::get_typename::name()) ) } - template inline void pack( Stream& s, const signed_int& v, uint32_t _max_depth ) { - uint32_t val = (v.value<<1) ^ (v.value>>31); - do { - uint8_t b = uint8_t(val) & 0x7f; - val >>= 7; - b |= ((val > 0) << 7); - s.write((char*)&b,1);//.put(b); - } while( val ); - } - template inline void pack( Stream& s, const unsigned_int& v, uint32_t _max_depth ) { uint64_t val = v.value; do { @@ -178,17 +168,6 @@ namespace fc { }while( val ); } - template inline void unpack( Stream& s, signed_int& vi, uint32_t _max_depth ) { - uint32_t v = 0; char b = 0; int by = 0; - do { - s.get(b); - v |= uint32_t(uint8_t(b) & 0x7f) << by; - by += 7; - } while( (uint8_t(b) & 0x80) && by < 32 ); - vi.value = ((v>>1) ^ (v>>31)) + (v&0x01); - vi.value = v&0x01 ? vi.value : -vi.value; - vi.value = -vi.value; - } template inline void unpack( Stream& s, unsigned_int& vi, uint32_t _max_depth ) { uint64_t v = 0; char b = 0; uint8_t by = 0; do { diff --git a/include/fc/io/raw_fwd.hpp b/include/fc/io/raw_fwd.hpp index 157a745..87a9208 100644 --- a/include/fc/io/raw_fwd.hpp +++ b/include/fc/io/raw_fwd.hpp @@ -116,9 +116,6 @@ namespace fc { template inline void pack( Stream& s, const std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void unpack( Stream& s, std::vector& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const signed_int& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void unpack( Stream& s, signed_int& vi, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); - template inline void pack( Stream& s, const unsigned_int& v, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); template inline void unpack( Stream& s, unsigned_int& vi, uint32_t _max_depth=FC_PACK_MAX_DEPTH ); diff --git a/include/fc/io/varint.hpp b/include/fc/io/varint.hpp index fe8e82e..30e42bb 100644 --- a/include/fc/io/varint.hpp +++ b/include/fc/io/varint.hpp @@ -33,42 +33,8 @@ struct unsigned_int { friend bool operator>=( const unsigned_int& i, const unsigned_int& v ) { return i.value >= v.value; } }; -/** - * @brief serializes a 32 bit signed interger in as few bytes as possible - * - * Uses the google protobuf algorithm for seralizing signed numbers - */ -struct signed_int { - signed_int( int32_t v = 0 ):value(v){} - operator int32_t()const { return value; } - template - signed_int& operator=( const T& v ) { value = v; return *this; } - signed_int operator++(int) { return value++; } - signed_int& operator++(){ ++value; return *this; } - - int32_t value; - - friend bool operator==( const signed_int& i, const int32_t& v ) { return i.value == v; } - friend bool operator==( const int32_t& i, const signed_int& v ) { return i == v.value; } - friend bool operator==( const signed_int& i, const signed_int& v ) { return i.value == v.value; } - - friend bool operator!=( const signed_int& i, const int32_t& v ) { return i.value != v; } - friend bool operator!=( const int32_t& i, const signed_int& v ) { return i != v.value; } - friend bool operator!=( const signed_int& i, const signed_int& v ) { return i.value != v.value; } - - friend bool operator<( const signed_int& i, const int32_t& v ) { return i.value < v; } - friend bool operator<( const int32_t& i, const signed_int& v ) { return i < v.value; } - friend bool operator<( const signed_int& i, const signed_int& v ) { return i.value < v.value; } - - friend bool operator>=( const signed_int& i, const int32_t& v ) { return i.value >= v; } - friend bool operator>=( const int32_t& i, const signed_int& v ) { return i >= v.value; } - friend bool operator>=( const signed_int& i, const signed_int& v ) { return i.value >= v.value; } -}; - class variant; -void to_variant( const signed_int& var, variant& vo, uint32_t max_depth = 1 ); -void from_variant( const variant& var, signed_int& vo, uint32_t max_depth = 1 ); void to_variant( const unsigned_int& var, variant& vo, uint32_t max_depth = 1 ); void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth = 1 ); @@ -77,15 +43,6 @@ void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth = 1 #include namespace std { - template<> - struct hash - { - public: - size_t operator()(const fc::signed_int &a) const - { - return std::hash()(a.value); - } - }; template<> struct hash { diff --git a/include/fc/reflect/typename.hpp b/include/fc/reflect/typename.hpp index 55695c2..7223d83 100644 --- a/include/fc/reflect/typename.hpp +++ b/include/fc/reflect/typename.hpp @@ -96,10 +96,8 @@ namespace fc { } }; - struct signed_int; struct unsigned_int; struct variant_object; - template<> struct get_typename { static const char* name() { return "signed_int"; } }; template<> struct get_typename { static const char* name() { return "unsigned_int"; } }; template<> struct get_typename { static const char* name() { return "fc::variant_object"; } }; diff --git a/src/io/varint.cpp b/src/io/varint.cpp index 6384eec..a5c6bbb 100644 --- a/src/io/varint.cpp +++ b/src/io/varint.cpp @@ -3,8 +3,6 @@ namespace fc { -void to_variant( const signed_int& var, variant& vo, uint32_t max_depth ) { vo = var.value; } -void from_variant( const variant& var, signed_int& vo, uint32_t max_depth ) { vo.value = static_cast(var.as_int64()); } void to_variant( const unsigned_int& var, variant& vo, uint32_t max_depth ) { vo = var.value; } void from_variant( const variant& var, unsigned_int& vo, uint32_t max_depth ) { vo.value = var.as_uint64(); } } diff --git a/tests/io/varint_tests.cpp b/tests/io/varint_tests.cpp index ea0ef58..1d5c67c 100644 --- a/tests/io/varint_tests.cpp +++ b/tests/io/varint_tests.cpp @@ -99,26 +99,6 @@ BOOST_AUTO_TEST_CASE( test_limits ) BOOST_CHECK_EQUAL( 0x4000000000000000ULL, unpacked_u[1].value ); BOOST_CHECK_EQUAL( 0x8000000000000000ULL, unpacked_u[2].value ); BOOST_CHECK_EQUAL( 0xc000000000000000ULL, unpacked_u[3].value ); - - /* Hm, seems that signed_int is broken, see below - static const std::string PACKED_S = "\04" - "\200\1" - "\200\200\200\200\04" - "\200\200\200\200\210" // not terminated - "\200\200\200\200\214"; // not terminated - std::vector unpacked_s; - fc::raw::unpack( std::vector( PACKED_S.begin(), PACKED_S.end() ), unpacked_s, 3 ); - BOOST_REQUIRE_EQUAL( 4, unpacked_s.size() ); - BOOST_CHECK_EQUAL( 0x40, unpacked_s[0].value ); - BOOST_CHECK_EQUAL( 0x20000000, unpacked_s[1].value ); - BOOST_CHECK_EQUAL( 0x40000000, unpacked_s[2].value ); - BOOST_CHECK_EQUAL( 0x60000000, unpacked_s[3].value ); - */ - - std::vector packed_s = fc::raw::pack( fc::signed_int(0x40000000), 3 ); - fc::signed_int tmp = fc::raw::unpack( packed_s, 3 ); - BOOST_CHECK_EQUAL( 0x40000000, tmp.value ); - } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_SUITE_END() From 79ff75423fb177db4efdc6428efccfcc2602133d Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Sun, 19 Aug 2018 18:51:45 +0200 Subject: [PATCH 09/10] Throw overflow_exception instead of silently cutting off data --- include/fc/io/raw.hpp | 4 +++- tests/io/varint_tests.cpp | 22 ++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index 48811c2..fb3abb7 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -172,9 +172,11 @@ namespace fc { uint64_t v = 0; char b = 0; uint8_t by = 0; do { s.get(b); + if( by >= 64 || (by == 63 && b > 1) ) + FC_THROW_EXCEPTION( overflow_exception, "Invalid packed unsigned_int!" ); v |= uint64_t(uint8_t(b) & 0x7f) << by; by += 7; - } while( (uint8_t(b) & 0x80) && by < 64 ); + } while( uint8_t(b) & 0x80 ); vi.value = static_cast(v); } diff --git a/tests/io/varint_tests.cpp b/tests/io/varint_tests.cpp index 1d5c67c..f1f1536 100644 --- a/tests/io/varint_tests.cpp +++ b/tests/io/varint_tests.cpp @@ -62,7 +62,7 @@ static const std::vector TEST_U = { 0xffffffffffffffffULL // \377\377\377\377\377\377\377\377\377\1 }; BOOST_AUTO_TEST_CASE( test_unsigned ) -{ +{ try { const std::vector packed_u = fc::raw::pack>( TEST_U, 3 ); BOOST_CHECK_EQUAL( UINT_LENGTH, packed_u.size() ); BOOST_CHECK_EQUAL( EXPECTED_UINTS, std::string( packed_u.data(), packed_u.size() ) ); @@ -83,22 +83,16 @@ BOOST_AUTO_TEST_CASE( test_unsigned ) BOOST_CHECK_EQUAL( TEST_U.size(), unjson_u.size() ); for( size_t i = 0; i < TEST_U.size(); i++ ) BOOST_CHECK_EQUAL( TEST_U[i].value, unjson_u[i].value ); -} +} FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_CASE( test_limits ) { try { - static const std::string PACKED_U = "\04" - "\200\1" - "\200\200\200\200\200\200\200\200\100" - "\200\200\200\200\200\200\200\200\200\201" // not terminated - "\200\200\200\200\200\200\200\200\300\201"; // not terminated - std::vector unpacked_u; - fc::raw::unpack( std::vector( PACKED_U.begin(), PACKED_U.end() ), unpacked_u, 3 ); - BOOST_REQUIRE_EQUAL( 4, unpacked_u.size() ); - BOOST_CHECK_EQUAL( 0x80, unpacked_u[0].value ); - BOOST_CHECK_EQUAL( 0x4000000000000000ULL, unpacked_u[1].value ); - BOOST_CHECK_EQUAL( 0x8000000000000000ULL, unpacked_u[2].value ); - BOOST_CHECK_EQUAL( 0xc000000000000000ULL, unpacked_u[3].value ); + static const std::string overflow = "\200\200\200\200\200\200\200\200\200\2"; // = 2^64 + static const std::string overlong = "\200\200\200\200\200\200\200\200\300\200\1"; + + fc::unsigned_int dest; + BOOST_CHECK_THROW( fc::raw::unpack( std::vector( overflow.begin(), overflow.end() ), dest, 3 ), fc::overflow_exception ); + BOOST_CHECK_THROW( fc::raw::unpack( std::vector( overlong.begin(), overlong.end() ), dest, 3 ), fc::overflow_exception ); } FC_LOG_AND_RETHROW() } BOOST_AUTO_TEST_SUITE_END() From 02a45166102305e34d968077baa54a8b8ba903a9 Mon Sep 17 00:00:00 2001 From: Peter Conrad Date: Tue, 21 Aug 2018 16:48:00 +0200 Subject: [PATCH 10/10] Handle b<0 --- include/fc/io/raw.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/fc/io/raw.hpp b/include/fc/io/raw.hpp index fb3abb7..c12abb1 100644 --- a/include/fc/io/raw.hpp +++ b/include/fc/io/raw.hpp @@ -172,7 +172,7 @@ namespace fc { uint64_t v = 0; char b = 0; uint8_t by = 0; do { s.get(b); - if( by >= 64 || (by == 63 && b > 1) ) + if( by >= 64 || (by == 63 && uint8_t(b) > 1) ) FC_THROW_EXCEPTION( overflow_exception, "Invalid packed unsigned_int!" ); v |= uint64_t(uint8_t(b) & 0x7f) << by; by += 7;