2424#include < cstring>
2525#include < limits>
2626
27+ #include " memory_operations.hpp"
28+
2729namespace datasketches {
2830
2931// clang++ seems to require this declaration for CMAKE_BUILD_TYPE='Debug"
@@ -209,6 +211,7 @@ vector_u8<A> frequent_items_sketch<T, W, H, E, S, A>::serialize(unsigned header_
209211 const size_t size = header_size_bytes + get_serialized_size_bytes ();
210212 vector_u8<A> bytes (size);
211213 uint8_t * ptr = bytes.data () + header_size_bytes;
214+ uint8_t * end_ptr = ptr + size;
212215
213216 const uint8_t preamble_longs = is_empty () ? PREAMBLE_LONGS_EMPTY : PREAMBLE_LONGS_NONEMPTY;
214217 ptr += copy_to_mem (&preamble_longs, ptr, sizeof (uint8_t ));
@@ -245,7 +248,8 @@ vector_u8<A> frequent_items_sketch<T, W, H, E, S, A>::serialize(unsigned header_
245248 }
246249 ptr += copy_to_mem (weights, ptr, sizeof (W) * num_items);
247250 AllocW ().deallocate (weights, num_items);
248- ptr += S ().serialize (ptr, items, num_items);
251+ const size_t bytes_remaining = end_ptr - ptr;
252+ ptr += S ().serialize (ptr, bytes_remaining, items, num_items);
249253 for (unsigned i = 0 ; i < num_items; i++) items[i].~T ();
250254 A ().deallocate (items, num_items);
251255 }
@@ -276,7 +280,7 @@ frequent_items_sketch<T, W, H, E, S, A> frequent_items_sketch<T, W, H, E, S, A>:
276280 check_family_id (family_id);
277281 check_size (lg_cur_size, lg_max_size);
278282
279- frequent_items_sketch<T, W, H, E, S, A> sketch (lg_cur_size, lg_max_size );
283+ frequent_items_sketch<T, W, H, E, S, A> sketch (lg_max_size, lg_cur_size );
280284 if (!is_empty) {
281285 uint32_t num_items;
282286 is.read ((char *)&num_items, sizeof (num_items));
@@ -308,7 +312,9 @@ frequent_items_sketch<T, W, H, E, S, A> frequent_items_sketch<T, W, H, E, S, A>:
308312
309313template <typename T, typename W, typename H, typename E, typename S, typename A>
310314frequent_items_sketch<T, W, H, E, S, A> frequent_items_sketch<T, W, H, E, S, A>::deserialize(const void * bytes, size_t size) {
315+ ensure_minimum_memory (size, 8 );
311316 const char * ptr = static_cast <const char *>(bytes);
317+ const char * base = static_cast <const char *>(bytes);
312318 uint8_t preamble_longs;
313319 ptr += copy_from_mem (ptr, &preamble_longs, sizeof (uint8_t ));
314320 uint8_t serial_version;
@@ -330,8 +336,9 @@ frequent_items_sketch<T, W, H, E, S, A> frequent_items_sketch<T, W, H, E, S, A>:
330336 check_serial_version (serial_version);
331337 check_family_id (family_id);
332338 check_size (lg_cur_size, lg_max_size);
339+ ensure_minimum_memory (size, 1 << preamble_longs);
333340
334- frequent_items_sketch<T, W, H, E, S, A> sketch (lg_cur_size, lg_max_size );
341+ frequent_items_sketch<T, W, H, E, S, A> sketch (lg_max_size, lg_cur_size );
335342 if (!is_empty) {
336343 uint32_t num_items;
337344 ptr += copy_from_mem (ptr, &num_items, sizeof (uint32_t ));
@@ -345,9 +352,11 @@ frequent_items_sketch<T, W, H, E, S, A> frequent_items_sketch<T, W, H, E, S, A>:
345352 // batch deserialization with intermediate array of items and weights
346353 typedef typename std::allocator_traits<A>::template rebind_alloc<W> AllocW;
347354 W* weights = AllocW ().allocate (num_items);
355+ ensure_minimum_memory (size, ptr - base + (sizeof (W) * num_items));
348356 ptr += copy_from_mem (ptr, weights, sizeof (W) * num_items);
349357 T* items = A ().allocate (num_items);
350- ptr += S ().deserialize (ptr, items, num_items);
358+ const size_t bytes_remaining = size - (ptr - base);
359+ ptr += S ().deserialize (ptr, bytes_remaining, items, num_items);
351360 for (uint32_t i = 0 ; i < num_items; i++) {
352361 sketch.update (std::move (items[i]), weights[i]);
353362 items[i].~T ();
@@ -436,7 +445,7 @@ void frequent_items_sketch<T, W, H, E, S, A>::check_weight(WW weight) {
436445// version for integral unsigned type - no-op
437446template <typename T, typename W, typename H, typename E, typename S, typename A>
438447template <typename WW, typename std::enable_if<std::is_integral<WW>::value && std::is_unsigned<WW>::value, int >::type>
439- void frequent_items_sketch<T, W, H, E, S, A>::check_weight(WW weight ) {}
448+ void frequent_items_sketch<T, W, H, E, S, A>::check_weight(WW) {}
440449
441450// version for floating point type
442451template <typename T, typename W, typename H, typename E, typename S, typename A>
0 commit comments