aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2021-01-06 13:19:58 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2021-01-07 20:24:51 +0000
commit89fe0e1c81718afe1882e526a2f0244e4dadae5c (patch)
treeffae5c3819cf065808f62456b5d2442efe07bdd2
parentMerge pull request #7282 (diff)
downloadmonero-89fe0e1c81718afe1882e526a2f0244e4dadae5c.tar.xz
storages: overridable limits for loading portable_storage from binary
-rw-r--r--contrib/epee/include/storages/http_abstract_invoke.h7
-rw-r--r--contrib/epee/include/storages/levin_abstract_invoke2.h15
-rw-r--r--contrib/epee/include/storages/portable_storage.h15
-rw-r--r--contrib/epee/include/storages/portable_storage_from_bin.h55
-rw-r--r--contrib/epee/include/storages/portable_storage_template_helper.h4
5 files changed, 63 insertions, 33 deletions
diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h
index a8bc945a8..08ac4c2ca 100644
--- a/contrib/epee/include/storages/http_abstract_invoke.h
+++ b/contrib/epee/include/storages/http_abstract_invoke.h
@@ -97,7 +97,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 cf1262486..e35ee30c5 100644
--- a/contrib/epee/include/storages/levin_abstract_invoke2.h
+++ b/contrib/epee/include/storages/levin_abstract_invoke2.h
@@ -50,6 +50,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
@@ -75,7 +80,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;
@@ -121,7 +126,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);
@@ -152,7 +157,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);
@@ -202,7 +207,7 @@ namespace epee
int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, std::string& 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);
@@ -236,7 +241,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 634af2d4e..1e68605ab 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(binarybuffer& target);
- 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);
@@ -150,7 +157,7 @@ namespace epee
CATCH_ENTRY("portable_storage::store_to_binary", false)
}
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))
@@ -173,6 +180,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);
diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h
index 08aad4b77..a31a794da 100644
--- a/contrib/epee/include/storages/portable_storage_from_bin.h
+++ b/contrib/epee/include/storages/portable_storage_from_bin.h
@@ -37,9 +37,6 @@
#else
#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL 100
#endif
-#define EPEE_PORTABLE_STORAGE_OBJECT_LIMIT_INTERNAL 65536
-#define EPEE_PORTABLE_STORAGE_OBJECT_FIELD_LIMIT_INTERNAL 65536
-#define EPEE_PORTABLE_STORAGE_STRING_LIMIT_INTERNAL 65536 // does not include field names
namespace epee
{
@@ -48,21 +45,20 @@ namespace epee
template<typename T>
struct ps_min_bytes {
static constexpr const size_t strict = 4096; // actual low bound
- static constexpr const size_t rough = 4096; // when we want to be stricter for DoS prevention
};
- template<> struct ps_min_bytes<uint64_t> { static constexpr const size_t strict = 8, rough = 8; };
- template<> struct ps_min_bytes<int64_t> { static constexpr const size_t strict = 8, rough = 8; };
- template<> struct ps_min_bytes<uint32_t> { static constexpr const size_t strict = 4, rough = 4; };
- template<> struct ps_min_bytes<int32_t> { static constexpr const size_t strict = 4, rough = 4; };
- template<> struct ps_min_bytes<uint16_t> { static constexpr const size_t strict = 2, rough = 2; };
- template<> struct ps_min_bytes<int16_t> { static constexpr const size_t strict = 2, rough = 2; };
- template<> struct ps_min_bytes<uint8_t> { static constexpr const size_t strict = 1, rough = 1; };
- template<> struct ps_min_bytes<int8_t> { static constexpr const size_t strict = 1, rough = 1; };
- template<> struct ps_min_bytes<double> { static constexpr const size_t strict = 8, rough = 8; };
- template<> struct ps_min_bytes<bool> { static constexpr const size_t strict = 1, rough = 1; };
- template<> struct ps_min_bytes<std::string> { static constexpr const size_t strict = 2, rough = 16; };
- template<> struct ps_min_bytes<section> { static constexpr const size_t strict = 1, rough = 256; };
- template<> struct ps_min_bytes<array_entry> { static constexpr const size_t strict = 1, rough = 128; };
+ 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
{
@@ -85,6 +81,7 @@ namespace epee
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
{
@@ -108,6 +105,10 @@ namespace epee
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)
@@ -122,6 +123,9 @@ namespace epee
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)
@@ -172,12 +176,12 @@ namespace epee
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 <= EPEE_PORTABLE_STORAGE_OBJECT_LIMIT_INTERNAL - m_objects, "Too many objects");
+ 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 <= EPEE_PORTABLE_STORAGE_STRING_LIMIT_INTERNAL - m_strings, "Too many strings");
+ CHECK_AND_ASSERT_THROW_MES(size <= max_strings - m_strings, "Too many strings");
m_strings += size;
}
@@ -246,7 +250,7 @@ namespace epee
inline storage_entry throwable_buffer_reader::read_se<std::string>()
{
RECURSION_LIMITATION();
- CHECK_AND_ASSERT_THROW_MES(m_strings + 1 <= EPEE_PORTABLE_STORAGE_STRING_LIMIT_INTERNAL, "Too many strings");
+ CHECK_AND_ASSERT_THROW_MES(m_strings + 1 <= max_strings, "Too many strings");
m_strings += 1;
return storage_entry(read<std::string>());
}
@@ -256,7 +260,7 @@ namespace epee
inline storage_entry throwable_buffer_reader::read_se<section>()
{
RECURSION_LIMITATION();
- CHECK_AND_ASSERT_THROW_MES(m_objects < EPEE_PORTABLE_STORAGE_OBJECT_LIMIT_INTERNAL, "Too many objects");
+ 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));
@@ -309,7 +313,7 @@ namespace epee
RECURSION_LIMITATION();
sec.m_entries.clear();
size_t count = read_varint();
- CHECK_AND_ASSERT_THROW_MES(count <= EPEE_PORTABLE_STORAGE_OBJECT_FIELD_LIMIT_INTERNAL - m_fields, "Too many object fields");
+ CHECK_AND_ASSERT_THROW_MES(count <= max_fields - m_fields, "Too many object fields");
m_fields += count;
while(count--)
{
@@ -339,5 +343,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 13c870d44..de6acfed8 100644
--- a/contrib/epee/include/storages/portable_storage_template_helper.h
+++ b/contrib/epee/include/storages/portable_storage_template_helper.h
@@ -84,10 +84,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;