Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
check_memory_span.hpp
Go to the documentation of this file.
1#pragma once
2// Note: heavy header due to serialization logic, don't include outside of tests
4
6#include "schema_name.hpp"
7#include <algorithm>
8#include <cstddef>
9#include <cstdint>
10#include <iostream>
11#include <vector>
12
13namespace msgpack {
14template <typename T> uintptr_t __aligned_for(uintptr_t ptr)
15{
16 // Round to next alignment, (ptr % alignof(T)) == 0 after
17 return ptr + (alignof(T) - (ptr % alignof(T))) % alignof(T);
18}
19template <typename T, typename... Args> std::string check_memory_span(T* obj, Args*... args)
20{
21 // We need to handle alignment. Thankfully, we have a tool here.
22 // Convert the variadic template arguments to a vector of pairs.
23 // Each pair contains a pointer (as uintptr_t) and its size.
24 std::vector<std::pair<uintptr_t, size_t>> pointers{ { (uintptr_t)(args), sizeof(Args) }... };
25
26 // Handle empty structs - if there are no fields, just return success
27 if (pointers.empty()) {
28 return {};
29 }
30
31 // Sort the vector based on the pointer values.
32 std::sort(pointers.begin(), pointers.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
33
34 for (size_t i = 1; i < pointers.size(); ++i) {
35 // Check if any of the Args* pointers overlap.
36 auto last_end = pointers[i - 1].first + pointers[i - 1].second;
37 if (last_end > pointers[i].first) {
38 return "Overlap in " + msgpack_schema_name(*obj) + " MSGPACK_FIELDS() params detected!";
39 }
40 // Check if gap is too large.
41 // Give some fuzzy room in case of 64 byte alignment restrictions.
42 if (__aligned_for<T>(last_end) < pointers[i].first) {
43 return "Gap in " + msgpack_schema_name(*obj) + " MSGPACK_FIELDS() params detected before member #" +
44 std::to_string(i) + " !";
45 }
46 }
47
48 // Check if all Args* pointers exist in T* memory.
49 uintptr_t t_start = reinterpret_cast<uintptr_t>(obj);
50 uintptr_t t_end = t_start + sizeof(T);
51 if (pointers.front().first < t_start || pointers.back().first + pointers.back().second > t_end) {
52 return "Some " + msgpack_schema_name(*obj) + " MSGPACK_FIELDS() params don't exist in object!";
53 }
54
55 // Check if all of T* memory is used by the Args* pointers.
56 size_t start = (size_t)obj;
57 size_t end = (size_t)obj;
58 for (auto [ptr, size] : pointers) {
59 end = std::max(end, ptr + size);
60 }
61 size_t total_size = end - start;
62 if (__aligned_for<T>(total_size) < sizeof(T)) {
63 return "Incomplete " + msgpack_schema_name(*obj) + " MSGPACK_FIELDS() params! Not all of object specified.";
64 }
65 return {};
66}
67
68template <msgpack_concepts::HasMsgPack T> std::string check_msgpack_method(const T& object)
69{
70 std::string result;
71 auto checker = [&](auto&... values) { result = check_memory_span(&object, &values...); };
72 const_cast<T&>(object).msgpack( // NOLINT
73 [&](auto&... keys_and_values) { std::apply(checker, drop_keys(std::tie(keys_and_values...))); });
74 return result;
75}
76void check_msgpack_usage(const auto& object)
77{
78 std::string result = check_msgpack_method(object);
79 if (!result.empty()) {
80 throw_or_abort(result);
81 }
82}
83} // namespace msgpack
FF a
FF b
std::string msgpack_schema_name(bb::g1::affine_element const &)
Definition g1.hpp:39
std::string check_msgpack_method(const T &object)
uintptr_t __aligned_for(uintptr_t ptr)
auto drop_keys(std::tuple< Args... > &&tuple)
Drops every first value pairwise of a flat argument tuple, assuming that they are keys.
Definition drop_keys.hpp:15
void check_msgpack_usage(const auto &object)
std::string check_memory_span(T *obj, Args *... args)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)
void throw_or_abort(std::string const &err)