diff options
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/epee/include/byte_stream.h | 2 | ||||
-rw-r--r-- | contrib/epee/include/net/abstract_tcp_server2.inl | 28 | ||||
-rw-r--r-- | contrib/epee/include/net/connection_basic.hpp | 4 | ||||
-rw-r--r-- | contrib/epee/include/net/levin_base.h | 3 | ||||
-rw-r--r-- | contrib/epee/include/net/levin_protocol_handler_async.h | 45 | ||||
-rw-r--r-- | contrib/epee/include/net/net_helper.h | 2 | ||||
-rw-r--r-- | contrib/epee/include/net/net_ssl.h | 1 | ||||
-rw-r--r-- | contrib/epee/include/rolling_median.h | 1 | ||||
-rw-r--r-- | contrib/epee/include/storages/http_abstract_invoke.h | 7 | ||||
-rw-r--r-- | contrib/epee/include/storages/levin_abstract_invoke2.h | 15 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage.h | 16 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_from_bin.h | 66 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_template_helper.h | 4 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_to_bin.h | 1 | ||||
-rw-r--r-- | contrib/epee/src/net_ssl.cpp | 3 | ||||
-rw-r--r-- | contrib/epee/src/readline_buffer.cpp | 18 | ||||
-rw-r--r-- | contrib/gitian/README.md | 1 |
17 files changed, 177 insertions, 40 deletions
diff --git a/contrib/epee/include/byte_stream.h b/contrib/epee/include/byte_stream.h index 30abd050d..93f9ac85c 100644 --- a/contrib/epee/include/byte_stream.h +++ b/contrib/epee/include/byte_stream.h @@ -175,7 +175,7 @@ namespace epee void put_n(const std::uint8_t ch, const std::size_t count) { check(count); - std::memset(tellp(), count, ch); + std::memset(tellp(), ch, count); next_write_ += count; } diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index cbacd118c..cb1388f3b 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -207,7 +207,6 @@ PRAGMA_WARNING_DISABLE_VS(4355) buffer_ssl_init_fill = 0; if (is_income && m_ssl_support != epee::net_utils::ssl_support_t::e_ssl_support_disabled) socket().async_receive(boost::asio::buffer(buffer_), - boost::asio::socket_base::message_peek, strand_.wrap( std::bind(&connection<t_protocol_handler>::handle_receive, self, std::placeholders::_1, @@ -334,6 +333,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) TRY_ENTRY(); //_info("[sock " << socket().native_handle() << "] Async read calledback."); + if (m_was_shutdown) + return; + if (!e) { double current_speed_down; @@ -360,6 +362,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) CRITICAL_REGION_LOCAL( epee::net_utils::network_throttle_manager::m_lock_get_global_throttle_in ); delay = epee::net_utils::network_throttle_manager::get_global_throttle_in().get_sleep_time_after_tick( bytes_transferred ); } + + if (m_was_shutdown) + return; delay *= 0.5; long int ms = (long int)(delay * 100); @@ -431,6 +436,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) std::size_t bytes_transferred) { TRY_ENTRY(); + + if (m_was_shutdown) return; + if (e) { // offload the error case @@ -438,13 +446,11 @@ PRAGMA_WARNING_DISABLE_VS(4355) return; } - reset_timer(get_timeout_from_bytes_read(bytes_transferred), false); - buffer_ssl_init_fill += bytes_transferred; - if (buffer_ssl_init_fill <= get_ssl_magic_size()) + MTRACE("we now have " << buffer_ssl_init_fill << "/" << get_ssl_magic_size() << " bytes needed to detect SSL"); + if (buffer_ssl_init_fill < get_ssl_magic_size()) { socket().async_receive(boost::asio::buffer(buffer_.data() + buffer_ssl_init_fill, buffer_.size() - buffer_ssl_init_fill), - boost::asio::socket_base::message_peek, strand_.wrap( boost::bind(&connection<t_protocol_handler>::handle_receive, connection<t_protocol_handler>::shared_from_this(), boost::asio::placeholders::error, @@ -470,7 +476,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) if (m_ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled) { // Handshake - if (!handshake(boost::asio::ssl::stream_base::server)) + if (!handshake(boost::asio::ssl::stream_base::server, boost::asio::const_buffer(buffer_.data(), buffer_ssl_init_fill))) { MERROR("SSL handshake failed"); boost::interprocess::ipcdetail::atomic_write32(&m_want_close_connection, 1); @@ -485,6 +491,11 @@ PRAGMA_WARNING_DISABLE_VS(4355) return; } } + else + { + handle_read(e, buffer_ssl_init_fill); + return; + } async_read_some(boost::asio::buffer(buffer_), strand_.wrap( @@ -651,6 +662,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) boost::this_thread::sleep(boost::posix_time::milliseconds( ms ) ); m_send_que_lock.lock(); _dbg1("sleep for queue: " << ms); + if (m_was_shutdown) + return false; if (retry > retry_limit) { MWARNING("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection"); @@ -748,7 +761,8 @@ PRAGMA_WARNING_DISABLE_VS(4355) template<class t_protocol_handler> void connection<t_protocol_handler>::reset_timer(boost::posix_time::milliseconds ms, bool add) { - if (ms.total_milliseconds() < 0) + const auto tms = ms.total_milliseconds(); + if (tms < 0 || (add && tms == 0)) { MWARNING("Ignoring negative timeout " << ms); return; diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 90303a785..23873f65b 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -132,10 +132,10 @@ class connection_basic { // not-templated base class for rapid developmet of som ssl_support_t get_ssl_support() const { return m_ssl_support; } void disable_ssl() { m_ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_disabled; } - bool handshake(boost::asio::ssl::stream_base::handshake_type type) + bool handshake(boost::asio::ssl::stream_base::handshake_type type, boost::asio::const_buffer buffer = {}) { //m_state != nullptr verified in constructor - return m_state->ssl_options().handshake(socket_, type); + return m_state->ssl_options().handshake(socket_, type, buffer); } template<typename MutableBufferSequence, typename ReadHandler> diff --git a/contrib/epee/include/net/levin_base.h b/contrib/epee/include/net/levin_base.h index ad561c5b6..fce6d4b7e 100644 --- a/contrib/epee/include/net/levin_base.h +++ b/contrib/epee/include/net/levin_base.h @@ -72,7 +72,8 @@ namespace levin #define LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED 0 -#define LEVIN_DEFAULT_MAX_PACKET_SIZE 100000000 //100MB by default +#define LEVIN_INITIAL_MAX_PACKET_SIZE 256*1024 // 256 KiB before handshake +#define LEVIN_DEFAULT_MAX_PACKET_SIZE 100000000 //100MB by default after handshake #define LEVIN_PACKET_REQUEST 0x00000001 #define LEVIN_PACKET_RESPONSE 0x00000002 diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index 8cb2be3e1..ddde701ee 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -84,7 +84,8 @@ class async_protocol_handler_config public: typedef t_connection_context connection_context; - uint64_t m_max_packet_size; + uint64_t m_initial_max_packet_size; + uint64_t m_max_packet_size; uint64_t m_invoke_timeout; int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, boost::uuids::uuid connection_id); @@ -105,7 +106,7 @@ public: size_t get_in_connections_count(); void set_handler(levin_commands_handler<t_connection_context>* handler, void (*destroy)(levin_commands_handler<t_connection_context>*) = NULL); - async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_invoke_timeout(LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) + async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_initial_max_packet_size(LEVIN_INITIAL_MAX_PACKET_SIZE), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_invoke_timeout(LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED) {} ~async_protocol_handler_config() { set_handler(NULL, NULL); } void del_out_connections(size_t count); @@ -162,6 +163,7 @@ public: net_utils::i_service_endpoint* m_pservice_endpoint; config_type& m_config; t_connection_context& m_connection_context; + std::atomic<uint64_t> m_max_packet_size; net_utils::buffer m_cache_in_buffer; stream_state m_state; @@ -289,7 +291,8 @@ public: m_current_head(bucket_head2()), m_pservice_endpoint(psnd_hndlr), m_config(config), - m_connection_context(conn_context), + m_connection_context(conn_context), + m_max_packet_size(config.m_initial_max_packet_size), m_cache_in_buffer(4 * 1024), m_state(stream_state_head) { @@ -399,13 +402,14 @@ public: } // these should never fail, but do runtime check for safety - CHECK_AND_ASSERT_MES(m_config.m_max_packet_size >= m_cache_in_buffer.size(), false, "Bad m_cache_in_buffer.size()"); - CHECK_AND_ASSERT_MES(m_config.m_max_packet_size - m_cache_in_buffer.size() >= m_fragment_buffer.size(), false, "Bad m_cache_in_buffer.size() + m_fragment_buffer.size()"); + const uint64_t max_packet_size = m_max_packet_size; + CHECK_AND_ASSERT_MES(max_packet_size >= m_cache_in_buffer.size(), false, "Bad m_cache_in_buffer.size()"); + CHECK_AND_ASSERT_MES(max_packet_size - m_cache_in_buffer.size() >= m_fragment_buffer.size(), false, "Bad m_cache_in_buffer.size() + m_fragment_buffer.size()"); // flipped to subtraction; prevent overflow since m_max_packet_size is variable and public - if(cb > m_config.m_max_packet_size - m_cache_in_buffer.size() - m_fragment_buffer.size()) + if(cb > max_packet_size - m_cache_in_buffer.size() - m_fragment_buffer.size()) { - MWARNING(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size + MWARNING(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << max_packet_size << ", packet received " << m_cache_in_buffer.size() + cb << ", connection will be closed."); return false; @@ -430,7 +434,7 @@ public: //async call scenario boost::shared_ptr<invoke_response_handler_base> response_handler = m_invoke_response_handlers.front(); response_handler->reset_timer(); - MDEBUG(m_connection_context << "LEVIN_PACKET partial msg received. len=" << cb); + MDEBUG(m_connection_context << "LEVIN_PACKET partial msg received. len=" << cb << ", current total " << m_cache_in_buffer.size() << "/" << m_current_head.m_cb << " (" << (100.0f * m_cache_in_buffer.size() / (m_current_head.m_cb ? m_current_head.m_cb : 1)) << "%)"); } } break; @@ -465,6 +469,14 @@ public: temp = std::move(m_fragment_buffer); m_fragment_buffer.clear(); std::memcpy(std::addressof(m_current_head), std::addressof(temp[0]), sizeof(bucket_head2)); + const size_t max_bytes = m_connection_context.get_max_bytes(m_current_head.m_command); + if(m_current_head.m_cb > std::min<size_t>(max_packet_size, max_bytes)) + { + MERROR(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << std::min<size_t>(max_packet_size, max_bytes) + << ", packet header received " << m_current_head.m_cb << ", command " << m_current_head.m_command + << ", connection will be closed."); + return false; + } buff_to_invoke = {reinterpret_cast<const uint8_t*>(temp.data()) + sizeof(bucket_head2), temp.size() - sizeof(bucket_head2)}; } @@ -519,6 +531,10 @@ public: m_current_head.m_command, buff_to_invoke, return_buff, m_connection_context ); + // peer_id remains unset if dropped + if (m_current_head.m_command == m_connection_context.handshake_command() && m_connection_context.handshake_complete()) + m_max_packet_size = m_config.m_max_packet_size; + bucket_head2 head = make_header(m_current_head.m_command, return_buff.size(), LEVIN_PACKET_RESPONSE, false); head.m_return_code = SWAP32LE(return_code); @@ -576,10 +592,11 @@ public: m_cache_in_buffer.erase(sizeof(bucket_head2)); m_state = stream_state_body; m_oponent_protocol_ver = m_current_head.m_protocol_version; - if(m_current_head.m_cb > m_config.m_max_packet_size) + const size_t max_bytes = m_connection_context.get_max_bytes(m_current_head.m_command); + if(m_current_head.m_cb > std::min<size_t>(max_packet_size, max_bytes)) { - LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size - << ", packet header received " << m_current_head.m_cb + LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << std::min<size_t>(max_packet_size, max_bytes) + << ", packet header received " << m_current_head.m_cb << ", command " << m_current_head.m_command << ", connection will be closed."); return false; } @@ -633,6 +650,9 @@ public: boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); CRITICAL_REGION_BEGIN(m_invoke_response_handlers_lock); + if (command == m_connection_context.handshake_command()) + m_max_packet_size = m_config.m_max_packet_size; + if(!send_message(command, in_buff, LEVIN_PACKET_REQUEST, true)) { LOG_ERROR_CC(m_connection_context, "Failed to do_send"); @@ -674,6 +694,9 @@ public: boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0); + if (command == m_connection_context.handshake_command()) + m_max_packet_size = m_config.m_max_packet_size; + if (!send_message(command, in_buff, LEVIN_PACKET_REQUEST, true)) { LOG_ERROR_CC(m_connection_context, "Failed to send request"); diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 508c79d76..a1f44cab0 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -179,7 +179,7 @@ namespace net_utils // SSL Options if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { - if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, addr, timeout)) + if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout)) { if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 643b2c486..1b1577e77 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -132,6 +132,7 @@ namespace net_utils bool handshake( boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type, + boost::asio::const_buffer buffer = {}, const std::string& host = {}, std::chrono::milliseconds timeout = std::chrono::seconds(15)) const; }; diff --git a/contrib/epee/include/rolling_median.h b/contrib/epee/include/rolling_median.h index 088a71d3e..877814e57 100644 --- a/contrib/epee/include/rolling_median.h +++ b/contrib/epee/include/rolling_median.h @@ -141,7 +141,6 @@ public: rolling_median_t(rolling_median_t &&m) { - free(data); memcpy(this, &m, sizeof(rolling_median_t)); m.data = NULL; } diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h index c4cb91130..c615b20e6 100644 --- a/contrib/epee/include/storages/http_abstract_invoke.h +++ b/contrib/epee/include/storages/http_abstract_invoke.h @@ -98,7 +98,12 @@ namespace epee return false; } - return serialization::load_t_from_binary(result_struct, epee::strspan<uint8_t>(pri->m_body)); + static const constexpr epee::serialization::portable_storage::limits_t default_http_bin_limits = { + 65536 * 3, // objects + 65536 * 3, // fields + 65536 * 3, // strings + }; + return serialization::load_t_from_binary(result_struct, epee::strspan<uint8_t>(pri->m_body), &default_http_bin_limits); } template<class t_request, class t_response, class t_transport> diff --git a/contrib/epee/include/storages/levin_abstract_invoke2.h b/contrib/epee/include/storages/levin_abstract_invoke2.h index 95f0bb410..802e16c1b 100644 --- a/contrib/epee/include/storages/levin_abstract_invoke2.h +++ b/contrib/epee/include/storages/levin_abstract_invoke2.h @@ -52,6 +52,11 @@ namespace snprintf(buf, sizeof(buf), "command-%u", command); return on_levin_traffic(context, initiator, sent, error, bytes, buf); } + static const constexpr epee::serialization::portable_storage::limits_t default_levin_limits = { + 8192, // objects + 16384, // fields + 16384, // strings + }; } namespace epee @@ -77,7 +82,7 @@ namespace epee return false; } serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff_to_recv)) + if(!stg_ret.load_from_binary(buff_to_recv, &default_levin_limits)) { LOG_ERROR("Failed to load_from_binary on command " << command); return false; @@ -124,7 +129,7 @@ namespace epee return false; } typename serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff_to_recv)) + if(!stg_ret.load_from_binary(buff_to_recv, &default_levin_limits)) { on_levin_traffic(context, true, false, true, buff_to_recv.size(), command); LOG_ERROR("Failed to load_from_binary on command " << command); @@ -155,7 +160,7 @@ namespace epee return false; } serialization::portable_storage stg_ret; - if(!stg_ret.load_from_binary(buff)) + if(!stg_ret.load_from_binary(buff, &default_levin_limits)) { on_levin_traffic(context, true, false, true, buff.size(), command); LOG_ERROR("Failed to load_from_binary on command " << command); @@ -205,7 +210,7 @@ namespace epee int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, byte_slice& buff_out, callback_t cb, t_context& context ) { serialization::portable_storage strg; - if(!strg.load_from_binary(in_buff)) + if(!strg.load_from_binary(in_buff, &default_levin_limits)) { on_levin_traffic(context, false, false, true, in_buff.size(), command); LOG_ERROR("Failed to load_from_binary in command " << command); @@ -239,7 +244,7 @@ namespace epee int buff_to_t_adapter(t_owner* powner, int command, const epee::span<const uint8_t> in_buff, callback_t cb, t_context& context) { serialization::portable_storage strg; - if(!strg.load_from_binary(in_buff)) + if(!strg.load_from_binary(in_buff, &default_levin_limits)) { on_levin_traffic(context, false, false, true, in_buff.size(), command); LOG_ERROR("Failed to load_from_binary in notify " << command); diff --git a/contrib/epee/include/storages/portable_storage.h b/contrib/epee/include/storages/portable_storage.h index 589e6ad63..f77e89cb6 100644 --- a/contrib/epee/include/storages/portable_storage.h +++ b/contrib/epee/include/storages/portable_storage.h @@ -54,6 +54,13 @@ namespace epee typedef epee::serialization::harray harray; typedef storage_entry meta_entry; + struct limits_t + { + size_t n_objects; + size_t n_fields; + size_t n_strings; // not counting field names + }; + portable_storage(){} virtual ~portable_storage(){} hsection open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist = false); @@ -84,8 +91,8 @@ namespace epee //------------------------------------------------------------------------------- bool store_to_binary(byte_slice& target, std::size_t initial_buffer_size = 8192); - bool load_from_binary(const epee::span<const uint8_t> target); - bool load_from_binary(const std::string& target) { return load_from_binary(epee::strspan<uint8_t>(target)); } + bool load_from_binary(const epee::span<const uint8_t> target, const limits_t *limits = NULL); + bool load_from_binary(const std::string& target, const limits_t *limits = NULL) { return load_from_binary(epee::strspan<uint8_t>(target), limits); } template<class trace_policy> bool dump_as_xml(std::string& targetObj, const std::string& root_name = ""); bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true); @@ -134,7 +141,7 @@ namespace epee return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format } inline - bool portable_storage::load_from_binary(const epee::span<const uint8_t> source) + bool portable_storage::load_from_binary(const epee::span<const uint8_t> source, const limits_t *limits) { m_root.m_entries.clear(); if(source.size() < sizeof(storage_block_header)) @@ -157,6 +164,8 @@ namespace epee } TRY_ENTRY(); throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header)); + if (limits) + buf_reader.set_limits(limits->n_objects, limits->n_fields, limits->n_strings); buf_reader.read(m_root); return true;//TODO: CATCH_ENTRY("portable_storage::load_from_binary", false); @@ -266,6 +275,7 @@ namespace epee static_assert(std::is_rvalue_reference<entry_type&&>(), "unexpected copy of value"); TRY_ENTRY(); CHECK_AND_ASSERT(psection, nullptr); + CHECK_AND_ASSERT(!pentry_name.empty(), nullptr); auto ins_res = psection->m_entries.emplace(pentry_name, std::forward<entry_type>(entry)); return &ins_res.first->second; CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr); diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h index b39dc7c92..9e7b6ec34 100644 --- a/contrib/epee/include/storages/portable_storage_from_bin.h +++ b/contrib/epee/include/storages/portable_storage_from_bin.h @@ -29,6 +29,7 @@ #pragma once #include "misc_language.h" +#include "misc_log_ex.h" #include "portable_storage_base.h" #include "portable_storage_bin_utils.h" @@ -42,6 +43,24 @@ namespace epee { namespace serialization { + template<typename T> + struct ps_min_bytes { + static constexpr const size_t strict = 4096; // actual low bound + }; + template<> struct ps_min_bytes<uint64_t> { static constexpr const size_t strict = 8; }; + template<> struct ps_min_bytes<int64_t> { static constexpr const size_t strict = 8; }; + template<> struct ps_min_bytes<uint32_t> { static constexpr const size_t strict = 4; }; + template<> struct ps_min_bytes<int32_t> { static constexpr const size_t strict = 4; }; + template<> struct ps_min_bytes<uint16_t> { static constexpr const size_t strict = 2; }; + template<> struct ps_min_bytes<int16_t> { static constexpr const size_t strict = 2; }; + template<> struct ps_min_bytes<uint8_t> { static constexpr const size_t strict = 1; }; + template<> struct ps_min_bytes<int8_t> { static constexpr const size_t strict = 1; }; + template<> struct ps_min_bytes<double> { static constexpr const size_t strict = 8; }; + template<> struct ps_min_bytes<bool> { static constexpr const size_t strict = 1; }; + template<> struct ps_min_bytes<std::string> { static constexpr const size_t strict = 2; }; + template<> struct ps_min_bytes<section> { static constexpr const size_t strict = 1; }; + template<> struct ps_min_bytes<array_entry> { static constexpr const size_t strict = 1; }; + struct throwable_buffer_reader { throwable_buffer_reader(const void* ptr, size_t sz); @@ -61,6 +80,9 @@ namespace epee void read(section& sec); void read(std::string& str); void read(array_entry &ae); + template<class t_type> + size_t min_bytes() const; + void set_limits(size_t objects, size_t fields, size_t strings); private: struct recursuion_limitation_guard { @@ -81,6 +103,13 @@ namespace epee const uint8_t* m_ptr; size_t m_count; size_t m_recursion_count; + size_t m_objects; + size_t m_fields; + size_t m_strings; + + size_t max_objects; + size_t max_fields; + size_t max_strings; }; inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz) @@ -92,6 +121,12 @@ namespace epee m_ptr = (uint8_t*)ptr; m_count = sz; m_recursion_count = 0; + m_objects = 0; + m_fields = 0; + m_strings = 0; + max_objects = std::numeric_limits<size_t>::max(); + max_fields = std::numeric_limits<size_t>::max(); + max_strings = std::numeric_limits<size_t>::max(); } inline void throwable_buffer_reader::read(void* target, size_t count) @@ -108,6 +143,7 @@ namespace epee RECURSION_LIMITATION(); uint8_t name_len = 0; read(name_len); + CHECK_AND_ASSERT_THROW_MES(name_len > 0, "Section name is missing"); sce_name.resize(name_len); read((void*)sce_name.data(), name_len); } @@ -138,7 +174,18 @@ namespace epee //for pod types array_entry_t<type_name> sa; size_t size = read_varint(); - CHECK_AND_ASSERT_THROW_MES(size <= m_count, "Size sanity check failed"); + CHECK_AND_ASSERT_THROW_MES(size <= m_count / ps_min_bytes<type_name>::strict, "Size sanity check failed"); + if (std::is_same<type_name, section>()) + { + CHECK_AND_ASSERT_THROW_MES(size <= max_objects - m_objects, "Too many objects"); + m_objects += size; + } + else if (std::is_same<type_name, std::string>()) + { + CHECK_AND_ASSERT_THROW_MES(size <= max_strings - m_strings, "Too many strings"); + m_strings += size; + } + sa.reserve(size); //TODO: add some optimization here later while(size--) @@ -204,6 +251,8 @@ namespace epee inline storage_entry throwable_buffer_reader::read_se<std::string>() { RECURSION_LIMITATION(); + CHECK_AND_ASSERT_THROW_MES(m_strings + 1 <= max_strings, "Too many strings"); + m_strings += 1; return storage_entry(read<std::string>()); } @@ -212,6 +261,8 @@ namespace epee inline storage_entry throwable_buffer_reader::read_se<section>() { RECURSION_LIMITATION(); + CHECK_AND_ASSERT_THROW_MES(m_objects < max_objects, "Too many objects"); + ++m_objects; section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio storage_entry se(std::move(s)); section& section_entry = boost::get<section>(se); @@ -263,12 +314,16 @@ namespace epee RECURSION_LIMITATION(); sec.m_entries.clear(); size_t count = read_varint(); + CHECK_AND_ASSERT_THROW_MES(count <= max_fields - m_fields, "Too many object fields"); + m_fields += count; while(count--) { //read section name string std::string sec_name; read_sec_name(sec_name); - sec.m_entries.emplace(std::move(sec_name), load_storage_entry()); + const auto insert_loc = sec.m_entries.lower_bound(sec_name); + CHECK_AND_ASSERT_THROW_MES(insert_loc == sec.m_entries.end() || insert_loc->first != sec_name, "duplicate key: " << sec_name); + sec.m_entries.emplace_hint(insert_loc, std::move(sec_name), load_storage_entry()); } } inline @@ -289,5 +344,12 @@ namespace epee RECURSION_LIMITATION(); CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported"); } + inline + void throwable_buffer_reader::set_limits(size_t objects, size_t fields, size_t strings) + { + max_objects = objects; + max_fields = fields; + max_strings = strings; + } } } diff --git a/contrib/epee/include/storages/portable_storage_template_helper.h b/contrib/epee/include/storages/portable_storage_template_helper.h index 39f900c8d..16dd565ec 100644 --- a/contrib/epee/include/storages/portable_storage_template_helper.h +++ b/contrib/epee/include/storages/portable_storage_template_helper.h @@ -85,10 +85,10 @@ namespace epee } //----------------------------------------------------------------------------------------------------------- template<class t_struct> - bool load_t_from_binary(t_struct& out, const epee::span<const uint8_t> binary_buff) + bool load_t_from_binary(t_struct& out, const epee::span<const uint8_t> binary_buff, const epee::serialization::portable_storage::limits_t *limits = NULL) { portable_storage ps; - bool rs = ps.load_from_binary(binary_buff); + bool rs = ps.load_from_binary(binary_buff, limits); if(!rs) return false; diff --git a/contrib/epee/include/storages/portable_storage_to_bin.h b/contrib/epee/include/storages/portable_storage_to_bin.h index 137497e19..49a7be185 100644 --- a/contrib/epee/include/storages/portable_storage_to_bin.h +++ b/contrib/epee/include/storages/portable_storage_to_bin.h @@ -211,6 +211,7 @@ namespace epee for(const section_pair& se: sec.m_entries) { CHECK_AND_ASSERT_THROW_MES(se.first.size() < std::numeric_limits<uint8_t>::max(), "storage_entry_name is too long: " << se.first.size() << ", val: " << se.first); + CHECK_AND_ASSERT_THROW_MES(!se.first.empty(), "storage_entry_name is empty"); uint8_t len = static_cast<uint8_t>(se.first.size()); strm.write((const char*)&len, sizeof(len)); strm.write(se.first.data(), size_t(len)); diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index a09e82771..6ed27efa9 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -473,6 +473,7 @@ bool ssl_options_t::has_fingerprint(boost::asio::ssl::verify_context &ctx) const bool ssl_options_t::handshake( boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type, + boost::asio::const_buffer buffer, const std::string& host, std::chrono::milliseconds timeout) const { @@ -530,7 +531,7 @@ bool ssl_options_t::handshake( }); boost::system::error_code ec = boost::asio::error::would_block; - socket.async_handshake(type, boost::lambda::var(ec) = boost::lambda::_1); + socket.async_handshake(type, boost::asio::buffer(buffer), boost::lambda::var(ec) = boost::lambda::_1); if (io_service.stopped()) { io_service.reset(); diff --git a/contrib/epee/src/readline_buffer.cpp b/contrib/epee/src/readline_buffer.cpp index bcf499963..1047d1696 100644 --- a/contrib/epee/src/readline_buffer.cpp +++ b/contrib/epee/src/readline_buffer.cpp @@ -6,6 +6,7 @@ #include <boost/thread/lock_guard.hpp> #include <boost/algorithm/string.hpp> +static bool same_as_last_line(const std::string&); static void install_line_handler(); static void remove_line_handler(); @@ -175,8 +176,11 @@ static void handle_line(char* line) boost::trim_right(test_line); if(!test_line.empty()) { - add_history(test_line.c_str()); - history_set_pos(history_length); + if (!same_as_last_line(test_line)) + { + add_history(test_line.c_str()); + history_set_pos(history_length); + } if (test_line == "exit" || test_line == "q") exit = true; } @@ -192,6 +196,16 @@ static void handle_line(char* line) return; } +// same_as_last_line returns true, if the last line in the history is +// equal to test_line. +static bool same_as_last_line(const std::string& test_line) +{ + // Note that state->offset == state->length, when a new line was entered. + HISTORY_STATE* state = history_get_history_state(); + return state->length > 0 + && test_line.compare(state->entries[state->length-1]->line) == 0; +} + static char* completion_matches(const char* text, int state) { static size_t list_index; diff --git a/contrib/gitian/README.md b/contrib/gitian/README.md index 1938462aa..e2e1d0b94 100644 --- a/contrib/gitian/README.md +++ b/contrib/gitian/README.md @@ -188,6 +188,7 @@ gpg --detach-sign ${VERSION}-linux/${GH_USER}/monero-linux-*-build.assert gpg --detach-sign ${VERSION}-win/${GH_USER}/monero-win-*-build.assert gpg --detach-sign ${VERSION}-osx/${GH_USER}/monero-osx-*-build.assert gpg --detach-sign ${VERSION}-android/${GH_USER}/monero-android-*-build.assert +gpg --detach-sign ${VERSION}-freebsd/${GH_USER}/monero-freebsd-*-build.assert ``` This will create a `.sig` file for each `.assert` file above (2 files for each platform). |