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#ifdef EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
37#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL EPEE_PORTABLE_STORAGE_RECURSION_LIMIT
38#else
39#define EPEE_PORTABLE_STORAGE_RECURSION_LIMIT_INTERNAL 100
40#endif
41
42namespace epee
43{
44 namespace serialization
45 {
46 template<typename T>
47 struct ps_min_bytes {
48 static constexpr const size_t strict = 4096; // actual low bound
49 };
50 template<> struct ps_min_bytes<uint64_t> { static constexpr const size_t strict = 8; };
51 template<> struct ps_min_bytes<int64_t> { static constexpr const size_t strict = 8; };
52 template<> struct ps_min_bytes<uint32_t> { static constexpr const size_t strict = 4; };
53 template<> struct ps_min_bytes<int32_t> { static constexpr const size_t strict = 4; };
54 template<> struct ps_min_bytes<uint16_t> { static constexpr const size_t strict = 2; };
55 template<> struct ps_min_bytes<int16_t> { static constexpr const size_t strict = 2; };
56 template<> struct ps_min_bytes<uint8_t> { static constexpr const size_t strict = 1; };
57 template<> struct ps_min_bytes<int8_t> { static constexpr const size_t strict = 1; };
58 template<> struct ps_min_bytes<double> { static constexpr const size_t strict = 8; };
59 template<> struct ps_min_bytes<bool> { static constexpr const size_t strict = 1; };
60 template<> struct ps_min_bytes<std::string> { static constexpr const size_t strict = 2; };
61 template<> struct ps_min_bytes<section> { static constexpr const size_t strict = 1; };
62 template<> struct ps_min_bytes<array_entry> { static constexpr const size_t strict = 1; };
63
65 {
66 throwable_buffer_reader(const void* ptr, size_t sz);
67 void read(void* target, size_t count);
68 void read_sec_name(std::string& sce_name);
69 template<class t_pod_type>
70 void read(t_pod_type& pod_val);
71 template<class t_type>
72 t_type read();
73 template<class type_name>
76 size_t read_varint();
77 template<class t_type>
80 void read(section& sec);
81 void read(std::string& str);
82 void read(array_entry &ae);
83 template<class t_type>
84 size_t min_bytes() const;
85 void set_limits(size_t objects, size_t fields, size_t strings);
86 private:
88 {
91 {
93 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");
94 }
96 {
97 CHECK_AND_ASSERT_THROW_MES(m_counter_ref != 0, "Internal error: m_counter_ref == 0 while ~recursuion_limitation_guard()");
99 }
100 };
101#define RECURSION_LIMITATION() recursuion_limitation_guard rl(m_recursion_count)
102
104 size_t m_count;
106 size_t m_objects;
107 size_t m_fields;
108 size_t m_strings;
109
113 };
114
115 inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz)
116 {
117 if(!ptr)
118 throw std::runtime_error("throwable_buffer_reader: ptr==nullptr");
119 if(!sz)
120 throw std::runtime_error("throwable_buffer_reader: sz==0");
121 m_ptr = (uint8_t*)ptr;
122 m_count = sz;
124 m_objects = 0;
125 m_fields = 0;
126 m_strings = 0;
127 max_objects = std::numeric_limits<size_t>::max();
128 max_fields = std::numeric_limits<size_t>::max();
129 max_strings = std::numeric_limits<size_t>::max();
130 }
131 inline
132 void throwable_buffer_reader::read(void* target, size_t count)
133 {
135 CHECK_AND_ASSERT_THROW_MES(m_count >= count, " attempt to read " << count << " bytes from buffer with " << m_count << " bytes remained");
136 memcpy(target, m_ptr, count);
137 m_ptr += count;
138 m_count -= count;
139 }
140 inline
141 void throwable_buffer_reader::read_sec_name(std::string& sce_name)
142 {
144 uint8_t name_len = 0;
145 read(name_len);
146 CHECK_AND_ASSERT_THROW_MES(name_len > 0, "Section name is missing");
147 sce_name.resize(name_len);
148 read((void*)sce_name.data(), name_len);
149 }
150
151 template<class t_pod_type>
152 void throwable_buffer_reader::read(t_pod_type& pod_val)
153 {
155 static_assert(std::is_pod<t_pod_type>::value, "POD type expected");
156 read(&pod_val, sizeof(pod_val));
157 pod_val = CONVERT_POD(pod_val);
158 }
159
160 template<>
161 void throwable_buffer_reader::read<bool>(bool& pod_val)
162 {
164 static_assert(std::is_pod<bool>::value, "POD type expected");
165 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!");
166 uint8_t t;
167 read(&t, sizeof(t));
168 CHECK_AND_ASSERT_THROW_MES(t <= 1, "Invalid bool value " << t);
169 pod_val = (t != 0);
170 }
171
172 template<class t_type>
174 {
176 t_type v;
177 read(v);
178 return v;
179 }
180
181
182 template<class type_name>
184 {
186 //for pod types
188 size_t size = read_varint();
189 CHECK_AND_ASSERT_THROW_MES(size <= m_count / ps_min_bytes<type_name>::strict, "Size sanity check failed");
190 if (std::is_same<type_name, section>())
191 {
192 CHECK_AND_ASSERT_THROW_MES(size <= max_objects - m_objects, "Too many objects");
193 m_objects += size;
194 }
195 else if (std::is_same<type_name, std::string>())
196 {
197 CHECK_AND_ASSERT_THROW_MES(size <= max_strings - m_strings, "Too many strings");
198 m_strings += size;
199 }
200
201 sa.reserve(size);
202 //TODO: add some optimization here later
203 while(size--)
204 sa.m_array.push_back(read<type_name>());
205 return storage_entry(array_entry(std::move(sa)));
206 }
207
208 inline
210 {
212 type &= ~SERIALIZE_FLAG_ARRAY;
213 switch(type)
214 {
215 case SERIALIZE_TYPE_INT64: return read_ae<int64_t>();
216 case SERIALIZE_TYPE_INT32: return read_ae<int32_t>();
217 case SERIALIZE_TYPE_INT16: return read_ae<int16_t>();
218 case SERIALIZE_TYPE_INT8: return read_ae<int8_t>();
219 case SERIALIZE_TYPE_UINT64: return read_ae<uint64_t>();
220 case SERIALIZE_TYPE_UINT32: return read_ae<uint32_t>();
221 case SERIALIZE_TYPE_UINT16: return read_ae<uint16_t>();
222 case SERIALIZE_TYPE_UINT8: return read_ae<uint8_t>();
223 case SERIALIZE_TYPE_DOUBLE: return read_ae<double>();
224 case SERIALIZE_TYPE_BOOL: return read_ae<bool>();
225 case SERIALIZE_TYPE_STRING: return read_ae<std::string>();
226 case SERIALIZE_TYPE_OBJECT: return read_ae<section>();
227 case SERIALIZE_TYPE_ARRAY: return read_ae<array_entry>();
228 default:
229 CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << type);
230 }
231 }
232
233 inline
235 {
237 CHECK_AND_ASSERT_THROW_MES(m_count >= 1, "empty buff, expected place for varint");
238 size_t v = 0;
240 switch (size_mask)
241 {
242 case PORTABLE_RAW_SIZE_MARK_BYTE: v = read<uint8_t>();break;
243 case PORTABLE_RAW_SIZE_MARK_WORD: v = read<uint16_t>();break;
244 case PORTABLE_RAW_SIZE_MARK_DWORD: v = read<uint32_t>();break;
245 case PORTABLE_RAW_SIZE_MARK_INT64: v = read<uint64_t>();break;
246 default:
247 CHECK_AND_ASSERT_THROW_MES(false, "unknown varint size_mask = " << size_mask);
248 }
249 v >>= 2;
250 return v;
251 }
252
253 template<class t_type>
255 {
257 t_type v;
258 read(v);
259 return storage_entry(v);
260 }
261
262 template<>
263 inline storage_entry throwable_buffer_reader::read_se<std::string>()
264 {
266 CHECK_AND_ASSERT_THROW_MES(m_strings + 1 <= max_strings, "Too many strings");
267 m_strings += 1;
268 return storage_entry(read<std::string>());
269 }
270
271
272 template<>
273 inline storage_entry throwable_buffer_reader::read_se<section>()
274 {
276 CHECK_AND_ASSERT_THROW_MES(m_objects < max_objects, "Too many objects");
277 ++m_objects;
278 section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio
279 storage_entry se(std::move(s));
280 section& section_entry = boost::get<section>(se);
281 read(section_entry);
282 return se;
283 }
284
285 template<>
286 inline storage_entry throwable_buffer_reader::read_se<array_entry>()
287 {
289 uint8_t ent_type = 0;
290 read(ent_type);
291 CHECK_AND_ASSERT_THROW_MES(ent_type&SERIALIZE_FLAG_ARRAY, "wrong type sequenses");
292 return load_storage_array_entry(ent_type);
293 }
294
295 inline
297 {
299 uint8_t ent_type = 0;
300 read(ent_type);
301 if(ent_type&SERIALIZE_FLAG_ARRAY)
302 return load_storage_array_entry(ent_type);
303
304 switch(ent_type)
305 {
306 case SERIALIZE_TYPE_INT64: return read_se<int64_t>();
307 case SERIALIZE_TYPE_INT32: return read_se<int32_t>();
308 case SERIALIZE_TYPE_INT16: return read_se<int16_t>();
309 case SERIALIZE_TYPE_INT8: return read_se<int8_t>();
310 case SERIALIZE_TYPE_UINT64: return read_se<uint64_t>();
311 case SERIALIZE_TYPE_UINT32: return read_se<uint32_t>();
312 case SERIALIZE_TYPE_UINT16: return read_se<uint16_t>();
313 case SERIALIZE_TYPE_UINT8: return read_se<uint8_t>();
314 case SERIALIZE_TYPE_DOUBLE: return read_se<double>();
315 case SERIALIZE_TYPE_BOOL: return read_se<bool>();
317 case SERIALIZE_TYPE_OBJECT: return read_se<section>();
318 case SERIALIZE_TYPE_ARRAY: return read_se<array_entry>();
319 default:
320 CHECK_AND_ASSERT_THROW_MES(false, "unknown entry_type code = " << ent_type);
321 }
322 }
323 inline
325 {
327 sec.m_entries.clear();
328 size_t count = read_varint();
329 CHECK_AND_ASSERT_THROW_MES(count <= max_fields - m_fields, "Too many object fields");
330 m_fields += count;
331 while(count--)
332 {
333 //read section name string
334 std::string sec_name;
335 read_sec_name(sec_name);
336 const auto insert_loc = sec.m_entries.lower_bound(sec_name);
337 CHECK_AND_ASSERT_THROW_MES(insert_loc == sec.m_entries.end() || insert_loc->first != sec_name, "duplicate key: " << sec_name);
338 sec.m_entries.emplace_hint(insert_loc, std::move(sec_name), load_storage_entry());
339 }
340 }
341 inline
343 {
345 size_t len = read_varint();
346 CHECK_AND_ASSERT_THROW_MES(len < MAX_STRING_LEN_POSSIBLE, "to big string len value in storage: " << len);
347 CHECK_AND_ASSERT_THROW_MES(m_count >= len, "string len count value " << len << " goes out of remain storage len " << m_count);
348 //do this manually to avoid double memory write in huge strings (first time at resize, second at read)
349 str.assign((const char*)m_ptr, len);
350 m_ptr+=len;
351 m_count -= len;
352 }
353 inline
355 {
357 CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported");
358 }
359 inline
360 void throwable_buffer_reader::set_limits(size_t objects, size_t fields, size_t strings)
361 {
362 max_objects = objects;
363 max_fields = fields;
364 max_strings = strings;
365 }
366 }
367}
#define s(x, c)
Definition: aesb.c:47
void * memcpy(void *a, const void *b, size_t c)
Definition: glibc_compat.cpp:16
int * count
Definition: gmock_stress_test.cc:176
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:263
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:39
#define RECURSION_LIMITATION()
Definition: portable_storage_from_bin.h:101
const char *const str
Definition: portlistingparse.c:23
int bool
Definition: stdbool.h:35
#define false
Definition: stdbool.h:37
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
Definition: portable_storage_from_bin.h:47
static constexpr const size_t strict
Definition: portable_storage_from_bin.h:48
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:90
~recursuion_limitation_guard() noexcept(false)
Definition: portable_storage_from_bin.h:95
size_t & m_counter_ref
Definition: portable_storage_from_bin.h:89
Definition: portable_storage_from_bin.h:65
size_t read_varint()
Definition: portable_storage_from_bin.h:234
size_t max_strings
Definition: portable_storage_from_bin.h:112
storage_entry read_se()
Definition: portable_storage_from_bin.h:254
t_type read()
Definition: portable_storage_from_bin.h:173
void read_sec_name(std::string &sce_name)
Definition: portable_storage_from_bin.h:141
const uint8_t * m_ptr
Definition: portable_storage_from_bin.h:103
size_t m_count
Definition: portable_storage_from_bin.h:104
size_t max_objects
Definition: portable_storage_from_bin.h:110
storage_entry read_ae()
Definition: portable_storage_from_bin.h:183
storage_entry load_storage_array_entry(uint8_t type)
Definition: portable_storage_from_bin.h:209
throwable_buffer_reader(const void *ptr, size_t sz)
Definition: portable_storage_from_bin.h:115
size_t m_strings
Definition: portable_storage_from_bin.h:108
size_t m_fields
Definition: portable_storage_from_bin.h:107
size_t m_recursion_count
Definition: portable_storage_from_bin.h:105
storage_entry load_storage_entry()
Definition: portable_storage_from_bin.h:296
void set_limits(size_t objects, size_t fields, size_t strings)
Definition: portable_storage_from_bin.h:360
size_t m_objects
Definition: portable_storage_from_bin.h:106
size_t max_fields
Definition: portable_storage_from_bin.h:111