Monero
Loading...
Searching...
No Matches
portable_storage_from_bin.h
Go to the documentation of this file.
1// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11// * Neither the name of the Andrey N. Sabelnikov nor the
12// names of its contributors may be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26
27
28
29#pragma once
30
31#include "misc_language.h"
32#include "misc_log_ex.h"
35
36#undef MONERO_DEFAULT_LOG_CATEGORY
37#define MONERO_DEFAULT_LOG_CATEGORY "serialization"
38
39#ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
40#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
41#else
42#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL 100
43#endif
44
45namespace epee
46{
47 namespace serialization
48 {
49 template<typename T>
50 struct ps_min_bytes {
51 static constexpr const size_t strict = 4096; // actual low bound
52 };
53 template<> struct ps_min_bytes<uint64_t> { static constexpr const size_t strict = 8; };
54 template<> struct ps_min_bytes<int64_t> { static constexpr const size_t strict = 8; };
55 template<> struct ps_min_bytes<uint32_t> { static constexpr const size_t strict = 4; };
56 template<> struct ps_min_bytes<int32_t> { static constexpr const size_t strict = 4; };
57 template<> struct ps_min_bytes<uint16_t> { static constexpr const size_t strict = 2; };
58 template<> struct ps_min_bytes<int16_t> { static constexpr const size_t strict = 2; };
59 template<> struct ps_min_bytes<uint8_t> { static constexpr const size_t strict = 1; };
60 template<> struct ps_min_bytes<int8_t> { static constexpr const size_t strict = 1; };
61 template<> struct ps_min_bytes<double> { static constexpr const size_t strict = 8; };
62 template<> struct ps_min_bytes<bool> { static constexpr const size_t strict = 1; };
63 template<> struct ps_min_bytes<std::string> { static constexpr const size_t strict = 2; };
64 template<> struct ps_min_bytes<section> { static constexpr const size_t strict = 1; };
65 template<> struct ps_min_bytes<array_entry> { static constexpr const size_t strict = 1; };
66
68 {
69 throwable_buffer_reader(const void* ptr, size_t sz);
70 void read(void* target, size_t count);
71 void read_sec_name(std::string& sce_name);
72 template<class t_pod_type>
73 void read(t_pod_type& pod_val);
74 template<class t_type>
75 t_type read();
76 template<class type_name>
79 size_t read_varint();
80 template<class t_type>
83 void read(section& sec);
84 void read(std::string& str);
85 void read(array_entry &ae);
86 template<class t_type>
87 size_t min_bytes() const;
88 void set_limits(size_t objects, size_t fields, size_t strings);
89 private:
91 {
94 {
96 CHECK_AND_ASSERT_THROW_MES(m_counter_ref < EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL, "Wrong blob data in portable storage: recursion limitation (" << EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL << ") exceeded");
97 }
99 {
100 CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()");
102 }
103 };
104#define RECURSION_LIMITATION() recursuion_limitation_guard rl(m_recursion_count)
105
107 size_t m_count;
109 size_t m_objects;
110 size_t m_fields;
111 size_t m_strings;
112
116 };
117
118 inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz)
119 {
120 if(!ptr)
121 throw std::runtime_error("throwable_buffer_reader: ptr==nullptr");
122 if(!sz)
123 throw std::runtime_error("throwable_buffer_reader: sz==0");
124 m_ptr = (uint8_t*)ptr;
125 m_count = sz;
127 m_objects = 0;
128 m_fields = 0;
129 m_strings = 0;
130 max_objects = std::numeric_limits<size_t>::max();
131 max_fields = std::numeric_limits<size_t>::max();
132 max_strings = std::numeric_limits<size_t>::max();
133 }
134 inline
135 void throwable_buffer_reader::read(void* target, size_t count)
136 {
138 CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read " << count << " bytes from buffer with " << m_count << " bytes remained");
139 memcpy(target, m_ptr, count);
140 m_ptr += count;
141 m_count -= count;
142 }
143 inline
144 void throwable_buffer_reader::read_sec_name(std::string& sce_name)
145 {
147 uint8_t name_len = 0;
148 read(name_len);
149 CHECK_AND_ASSERT_THROW_MES(name_len > 0, "Section name is missing");
150 sce_name.resize(name_len);
151 read((void*)sce_name.data(), name_len);
152 }
153
154 template<class t_pod_type>
155 void throwable_buffer_reader::read(t_pod_type& pod_val)
156 {
158 static_assert(std::is_pod<t_pod_type>::value, "POD type expected");
159 read(&pod_val, sizeof(pod_val));
160 pod_val = CONVERT_POD(pod_val);
161 }
162
163 template<>
165 {
167 static_assert(std::is_pod<bool>::value, "POD type expected");
168 static_assert(sizeof(bool) == sizeof(uint8_t), "We really shouldn't use bool directly in serialization code. Replace it with uint8_t if this assert triggers!");
169 uint8_t t;
170 read(&t, sizeof(t));
171 CHECK_AND_ASSERT_THROW_MES(t <= 1, "Invalid bool value " << t);
172 pod_val = (t != 0);
173 }
174
175 template<class t_type>
177 {
179 t_type v;
180 read(v);
181 return v;
182 }
183
184
185 template<class type_name>
187 {
189 //for pod types
191 size_t size = read_varint();
192 CHECK_AND_ASSERT_THROW_MES(size <= m_count / ps_min_bytes<type_name>::strict, "Size sanity check failed");
193 if (std::is_same<type_name, section>())
194 {
195 CHECK_AND_ASSERT_THROW_MES(size <= max_objects - m_objects, "Too many objects");
196 m_objects += size;
197 }
198 else if (std::is_same<type_name, std::string>())
199 {
200 CHECK_AND_ASSERT_THROW_MES(size <= max_strings - m_strings, "Too many strings");
201 m_strings += size;
202 }
203
204 sa.reserve(size);
205 //TODO: add some optimization here later
206 while(size--)
207 sa.m_array.push_back(read<type_name>());
208 return storage_entry(array_entry(std::move(sa)));
209 }
210
211 inline
213 {
215 type &= ~SERIALIZE_FLAG_ARRAY;
216 switch(type)
217 {
227 case SERIALIZE_TYPE_BOOL: return read_ae<bool>();
231 default:
232 CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << type);
233 }
234 }
235
236 inline
238 {
240 CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint");
241 size_t v = 0;
243 switch (size_mask)
244 {
249 default:
250 CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = " << size_mask);
251 }
252 v >>= 2;
253 return v;
254 }
255
256 template<class t_type>
258 {
260 t_type v;
261 read(v);
262 return storage_entry(v);
263 }
264
265 template<>
267 {
269 CHECK_AND_ASSERT_THROW_MES(m_strings + 1 <= max_strings, "Too many strings");
270 m_strings += 1;
271 return storage_entry(read<std::string>());
272 }
273
274
275 template<>
277 {
279 CHECK_AND_ASSERT_THROW_MES(m_objects < max_objects, "Too many objects");
280 ++m_objects;
281 section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio
282 storage_entry se(std::move(s));
283 section& section_entry = boost::get<section>(se);
284 read(section_entry);
285 return se;
286 }
287
288 template<>
290 {
292 uint8_t ent_type = 0;
293 read(ent_type);
294 CHECK_AND_ASSERT_THROW_MES(ent_type&SERIALIZE_FLAG_ARRAY, "wrong type sequenses");
295 return load_storage_array_entry(ent_type);
296 }
297
298 inline
300 {
302 uint8_t ent_type = 0;
303 read(ent_type);
304 if(ent_type&SERIALIZE_FLAG_ARRAY)
305 return load_storage_array_entry(ent_type);
306
307 switch(ent_type)
308 {
318 case SERIALIZE_TYPE_BOOL: return read_se<bool>();
322 default:
323 CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << ent_type);
324 }
325 }
326 inline
328 {
330 sec.m_entries.clear();
331 size_t count = read_varint();
332 CHECK_AND_ASSERT_THROW_MES(count <= max_fields - m_fields, "Too many object fields");
333 m_fields += count;
334 while(count--)
335 {
336 //read section name string
337 std::string sec_name;
338 read_sec_name(sec_name);
339 const auto insert_loc = sec.m_entries.lower_bound(sec_name);
340 CHECK_AND_ASSERT_THROW_MES(insert_loc == sec.m_entries.end() || insert_loc->first != sec_name, "duplicate key: " << sec_name);
341 sec.m_entries.emplace_hint(insert_loc, std::move(sec_name), load_storage_entry());
342 }
343 }
344 inline
346 {
348 size_t len = read_varint();
349 CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: " << len);
350 CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value " << len << " goes out of remain storage len " << m_count);
351 //do this manually to avoid double memory write in huge strings (first time at resize, second at read)
352 str.assign((const char*)m_ptr, len);
353 m_ptr+=len;
354 m_count -= len;
355 }
356 inline
358 {
360 CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported");
361 }
362 inline
363 void throwable_buffer_reader::set_limits(size_t objects, size_t fields, size_t strings)
364 {
365 max_objects = objects;
366 max_fields = fields;
367 max_strings = strings;
368 }
369 }
370}
#define s(x, c)
Definition aesb.c:47
void * memcpy(void *a, const void *b, size_t c)
Definition glibc_compat.cpp:16
#define false
boost::variant< uint64_t, uint32_t, uint16_t, uint8_t, int64_t, int32_t, int16_t, int8_t, double, bool, std::string, section, array_entry > storage_entry
Definition portable_storage_base.h:161
storage_entry throwable_buffer_reader::read_se< std::string >()
Definition portable_storage_from_bin.h:266
boost::make_recursive_variant< array_entry_t< section >, array_entry_t< uint64_t >, array_entry_t< uint32_t >, array_entry_t< uint16_t >, array_entry_t< uint8_t >, array_entry_t< int64_t >, array_entry_t< int32_t >, array_entry_t< int16_t >, array_entry_t< int8_t >, array_entry_t< double >, array_entry_t< bool >, array_entry_t< std::string >, array_entry_t< section >, array_entry_t< boost::recursive_variant_ > >::type array_entry
Definition portable_storage_base.h:159
TODO: (mj-xmr) This will be reduced in an another PR.
Definition byte_slice.h:40
Definition binary_utils.h:36
Definition enums.h:68
#define PORTABLE_RAW_SIZE_MARK_WORD
Definition portable_storage_base.h:43
#define SERIALIZE_FLAG_ARRAY
Definition portable_storage_base.h:66
#define PORTABLE_RAW_SIZE_MARK_DWORD
Definition portable_storage_base.h:44
#define SERIALIZE_TYPE_UINT32
Definition portable_storage_base.h:57
#define SERIALIZE_TYPE_INT32
Definition portable_storage_base.h:53
#define MAX_STRING_LEN_POSSIBLE
Definition portable_storage_base.h:48
#define SERIALIZE_TYPE_UINT8
Definition portable_storage_base.h:59
#define PORTABLE_RAW_SIZE_MARK_MASK
Definition portable_storage_base.h:41
#define SERIALIZE_TYPE_UINT16
Definition portable_storage_base.h:58
#define PORTABLE_RAW_SIZE_MARK_BYTE
Definition portable_storage_base.h:42
#define PORTABLE_RAW_SIZE_MARK_INT64
Definition portable_storage_base.h:45
#define SERIALIZE_TYPE_INT64
Definition portable_storage_base.h:52
#define SERIALIZE_TYPE_UINT64
Definition portable_storage_base.h:56
#define SERIALIZE_TYPE_INT8
Definition portable_storage_base.h:55
#define SERIALIZE_TYPE_DOUBLE
Definition portable_storage_base.h:60
#define SERIALIZE_TYPE_STRING
Definition portable_storage_base.h:61
#define SERIALIZE_TYPE_INT16
Definition portable_storage_base.h:54
#define SERIALIZE_TYPE_OBJECT
Definition portable_storage_base.h:63
#define SERIALIZE_TYPE_ARRAY
Definition portable_storage_base.h:64
#define SERIALIZE_TYPE_BOOL
Definition portable_storage_base.h:62
#define CONVERT_POD(x)
Definition portable_storage_bin_utils.h:43
#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL
Definition portable_storage_from_bin.h:42
#define RECURSION_LIMITATION()
Definition portable_storage_from_bin.h:104
const char *const str
Definition portlistingparse.c:23
signed short int16_t
Definition stdint.h:122
unsigned short uint16_t
Definition stdint.h:125
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
signed int int32_t
Definition stdint.h:123
unsigned char uint8_t
Definition stdint.h:124
unsigned __int64 uint64_t
Definition stdint.h:136
signed char int8_t
Definition stdint.h:121
Definition portable_storage_base.h:83
void reserve(size_t n)
Definition portable_storage_base.h:134
entry_container< t_entry_type >::type m_array
Definition portable_storage_base.h:139
static constexpr const size_t strict
Definition portable_storage_from_bin.h:65
static constexpr const size_t strict
Definition portable_storage_from_bin.h:62
static constexpr const size_t strict
Definition portable_storage_from_bin.h:61
static constexpr const size_t strict
Definition portable_storage_from_bin.h:58
static constexpr const size_t strict
Definition portable_storage_from_bin.h:56
static constexpr const size_t strict
Definition portable_storage_from_bin.h:54
static constexpr const size_t strict
Definition portable_storage_from_bin.h:60
static constexpr const size_t strict
Definition portable_storage_from_bin.h:64
static constexpr const size_t strict
Definition portable_storage_from_bin.h:63
static constexpr const size_t strict
Definition portable_storage_from_bin.h:57
static constexpr const size_t strict
Definition portable_storage_from_bin.h:55
static constexpr const size_t strict
Definition portable_storage_from_bin.h:53
static constexpr const size_t strict
Definition portable_storage_from_bin.h:59
Definition portable_storage_from_bin.h:50
static constexpr const size_t strict
Definition portable_storage_from_bin.h:51
Definition portable_storage_base.h:169
std::map< std::string, storage_entry > m_entries
Definition portable_storage_base.h:170
recursuion_limitation_guard(size_t &counter)
Definition portable_storage_from_bin.h:93
~recursuion_limitation_guard() noexcept(false)
Definition portable_storage_from_bin.h:98
size_t & m_counter_ref
Definition portable_storage_from_bin.h:92
size_t read_varint()
Definition portable_storage_from_bin.h:237
size_t max_strings
Definition portable_storage_from_bin.h:115
storage_entry read_se()
Definition portable_storage_from_bin.h:257
t_type read()
Definition portable_storage_from_bin.h:176
void read_sec_name(std::string &sce_name)
Definition portable_storage_from_bin.h:144
const uint8_t * m_ptr
Definition portable_storage_from_bin.h:106
size_t m_count
Definition portable_storage_from_bin.h:107
size_t max_objects
Definition portable_storage_from_bin.h:113
storage_entry read_ae()
Definition portable_storage_from_bin.h:186
storage_entry load_storage_array_entry(uint8_t type)
Definition portable_storage_from_bin.h:212
throwable_buffer_reader(const void *ptr, size_t sz)
Definition portable_storage_from_bin.h:118
size_t m_strings
Definition portable_storage_from_bin.h:111
size_t m_fields
Definition portable_storage_from_bin.h:110
size_t m_recursion_count
Definition portable_storage_from_bin.h:108
storage_entry load_storage_entry()
Definition portable_storage_from_bin.h:299
void set_limits(size_t objects, size_t fields, size_t strings)
Definition portable_storage_from_bin.h:363
size_t m_objects
Definition portable_storage_from_bin.h:109
size_t max_fields
Definition portable_storage_from_bin.h:114
void read(void *target, size_t count)
Definition portable_storage_from_bin.h:135