Skip to content

Commit 0282554

Browse files
committed
Ensure alignment of data members of new-allocated objects
1 parent 43c4c6a commit 0282554

File tree

2 files changed

+41
-13
lines changed

2 files changed

+41
-13
lines changed

src/bsoncxx/lib/bsoncxx/v_noabi/bsoncxx/builder/core.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <bsoncxx/v1/detail/macros.hpp>
1616

1717
#include <cstring>
18+
#include <memory>
1819

1920
#include <bsoncxx/builder/core.hpp>
2021
#include <bsoncxx/exception/error_code.hpp>
@@ -72,14 +73,33 @@ class managed_bson_t {
7273

7374
class core::impl {
7475
public:
75-
impl(bool is_array) : _depth(0), _root_is_array(is_array), _n(0), _has_user_key(false) {}
76+
~impl() {
77+
_root_ptr->~managed_bson_t();
78+
}
79+
80+
impl(impl&&) = delete;
81+
impl& operator=(impl&&) = delete;
82+
83+
impl(impl const&) = delete;
84+
impl& operator=(impl const&) = delete;
85+
86+
impl(bool is_array)
87+
: _depth(0),
88+
_root_is_array(is_array),
89+
_n(0),
90+
_root_ptr([this] {
91+
void* ptr = _root_storage;
92+
std::size_t space = sizeof(_root_storage);
93+
return new (std::align(alignof(managed_bson_t), sizeof(managed_bson_t), ptr, space)) managed_bson_t();
94+
}()),
95+
_has_user_key(false) {}
7696

7797
void reinit() {
7898
while (!_stack.empty()) {
7999
_stack.pop_back();
80100
}
81101

82-
bson_reinit(_root.get());
102+
bson_reinit(_root_ptr->get());
83103

84104
_depth = 0;
85105

@@ -95,8 +115,8 @@ class core::impl {
95115
}
96116

97117
uint32_t buf_len;
98-
uint8_t* buf_ptr = bson_destroy_with_steal(_root.get(), true, &buf_len);
99-
bson_init(_root.get());
118+
uint8_t* buf_ptr = bson_destroy_with_steal(_root_ptr->get(), true, &buf_len);
119+
bson_init(_root_ptr->get());
100120

101121
return bsoncxx::v_noabi::document::value{buf_ptr, buf_len, bson_free_deleter};
102122
}
@@ -108,15 +128,15 @@ class core::impl {
108128
}
109129

110130
uint32_t buf_len;
111-
uint8_t* buf_ptr = bson_destroy_with_steal(_root.get(), true, &buf_len);
112-
bson_init(_root.get());
131+
uint8_t* buf_ptr = bson_destroy_with_steal(_root_ptr->get(), true, &buf_len);
132+
bson_init(_root_ptr->get());
113133

114134
return bsoncxx::v_noabi::array::value{buf_ptr, buf_len, bson_free_deleter};
115135
}
116136

117137
bson_t* back() {
118138
if (_stack.empty()) {
119-
return _root.get();
139+
return _root_ptr->get();
120140
} else {
121141
return &_stack.back().bson;
122142
}
@@ -178,7 +198,7 @@ class core::impl {
178198
throw bsoncxx::v_noabi::exception{error_code::k_cannot_perform_document_operation_on_array};
179199
}
180200

181-
return _root.get();
201+
return _root_ptr->get();
182202
}
183203

184204
// Throws bsoncxx::v_noabi::exception if the top-level BSON datum is a document.
@@ -187,7 +207,7 @@ class core::impl {
187207
throw bsoncxx::v_noabi::exception{error_code::k_cannot_perform_array_operation_on_document};
188208
}
189209

190-
return _root.get();
210+
return _root_ptr->get();
191211
}
192212

193213
bool is_array() {
@@ -239,7 +259,9 @@ class core::impl {
239259

240260
bool _root_is_array;
241261
std::size_t _n;
242-
managed_bson_t _root;
262+
263+
unsigned char _root_storage[2u * sizeof(managed_bson_t)];
264+
managed_bson_t* _root_ptr;
243265

244266
// The bottom frame of _stack has _root as its parent.
245267
stack<frame, 4> _stack;

src/mongocxx/lib/mongocxx/v_noabi/mongocxx/private/client_session.hh

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <mongocxx/v1/detail/macros.hpp>
1818

1919
#include <exception>
20+
#include <memory>
2021

2122
#include <bsoncxx/private/helpers.hh>
2223
#include <bsoncxx/private/libbson.hh>
@@ -73,7 +74,11 @@ bool with_transaction_cpp_cb(mongoc_client_session_t*, void* ctx, bson_t** reply
7374
class client_session::impl {
7475
public:
7576
impl(mongocxx::v_noabi::client const* client, options::client_session const& session_options)
76-
: _client(client), _options(session_options), _session_t(nullptr, nullptr) {
77+
: _client(client), _options(session_options), _session_t(nullptr, nullptr), _empty_cluster_time_ptr([this] {
78+
void* ptr = const_cast<void*>(static_cast<void const*>(_empty_cluster_time_storage));
79+
std::size_t space = sizeof(_empty_cluster_time_storage);
80+
return new (std::align(alignof(bson_t), sizeof(bson_t), ptr, space)) bson_t BSON_INITIALIZER;
81+
}()) {
7782
// Create a mongoc_session_opts_t from session_options.
7883
std::unique_ptr<mongoc_session_opt_t, decltype(libmongoc::session_opts_destroy)> opt_t{
7984
libmongoc::session_opts_new(), libmongoc::session_opts_destroy};
@@ -123,7 +128,7 @@ class client_session::impl {
123128
return bsoncxx::helpers::view_from_bson_t(ct);
124129
}
125130

126-
return bsoncxx::helpers::view_from_bson_t(&_empty_cluster_time);
131+
return bsoncxx::helpers::view_from_bson_t(_empty_cluster_time_ptr);
127132
}
128133

129134
bsoncxx::v_noabi::types::b_timestamp operation_time() const noexcept {
@@ -236,7 +241,8 @@ class client_session::impl {
236241

237242
unique_session _session_t;
238243

239-
bson_t _empty_cluster_time = BSON_INITIALIZER;
244+
unsigned char _empty_cluster_time_storage[2u * sizeof(bson_t)];
245+
bson_t const* _empty_cluster_time_ptr; // Just a long-lasting empty bson_t. Destruction is not required.
240246
};
241247

242248
} // namespace v_noabi

0 commit comments

Comments
 (0)