MySQL 9.3.0
Source Code Documentation
secure_string.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2025, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef ROUTER_SRC_HARNESS_INCLUDE_SECURE_STRING_H_
27#define ROUTER_SRC_HARNESS_INCLUDE_SECURE_STRING_H_
28
29#include <iterator>
30#include <memory>
31#include <string>
32#include <type_traits>
33#include <utility>
34
35#include "harness_export.h" // NOLINT(build/include_subdir)
36
37#ifndef __sun
38#include "secure_allocator.h" // NOLINT(build/include_subdir)
39#endif
40
41namespace mysql_harness {
42namespace detail {
43
44template <typename value_type, typename traits_type, typename allocator_type>
46 requires {
47 std::is_same_v<value_type, typename traits_type::char_type>;
48 std::is_same_v<value_type, typename allocator_type::value_type>;
49 };
50
51void HARNESS_EXPORT secure_wipe(void *ptr, std::size_t count);
52
53/**
54 * Null-terminated string which is securely wiped on destruction.
55 */
56template <typename CharT, typename Traits = std::char_traits<CharT>,
57 typename Allocator = std::allocator<CharT>>
59class SecureString final {
60 private:
61 using AllocatorTraits = std::allocator_traits<Allocator>;
62
63 public:
64 using traits_type = Traits;
65 using value_type = Traits::char_type;
66 using allocator_type = Allocator;
67
68 using size_type = AllocatorTraits::size_type;
69 using difference_type = AllocatorTraits::difference_type;
70
72 using const_reference = const value_type &;
73
74 using pointer = AllocatorTraits::pointer;
75 using const_pointer = AllocatorTraits::const_pointer;
76
77 /**
78 * Default constructor.
79 */
80 SecureString() noexcept : data_() { set_empty(); }
81
82 /**
83 * Constructor with an allocator.
84 */
85 explicit SecureString(const allocator_type &alloc) noexcept : data_(alloc) {
86 set_empty();
87 }
88
89 /**
90 * Copies the provided string, wiping the memory pointed by `ptr`.
91 *
92 * @param ptr Pointer to an array of characters.
93 * @param length Number of characters in the array.
94 * @param alloc Allocator to use.
95 */
97 const allocator_type &alloc = allocator_type())
98 : data_(alloc) {
99 if (length) [[likely]] {
101
102 assign(ptr, length);
103 traits_type::assign(data()[length], kNull);
104
105 wipe(ptr, length);
106 } else {
107 set_empty();
108 }
109 }
110
111 /**
112 * Copies the provided string, wiping the memory between `first` and `last`.
113 *
114 * @param first Beginning of a range.
115 * @param last End of a range.
116 * @param alloc Allocator to use.
117 */
118 template <typename InputIt>
119 SecureString(InputIt first, InputIt last,
120 const allocator_type &alloc = allocator_type())
121 : data_(alloc) {
122 if (const auto length = std::distance(first, last)) [[likely]] {
124
125 const auto ptr = reinterpret_cast<pointer>(&*first);
126
127 for (auto p = data(); first != last; ++first, ++p) {
128 traits_type::assign(*p, *first);
129 }
130
131 traits_type::assign(data()[length], kNull);
132
133 wipe(ptr, length);
134 } else {
135 set_empty();
136 }
137 }
138
139 /**
140 * Copies the provided string, wiping its memory.
141 *
142 * @param s String to be copied.
143 * @param alloc Allocator to use.
144 */
145 template <class StringTraits = std::char_traits<value_type>,
146 class StringAllocator = std::allocator<value_type>>
148 SecureString(std::basic_string<value_type, StringTraits, StringAllocator> &&s,
149 const allocator_type &alloc = allocator_type())
150 : data_(alloc) {
151 if (!s.empty()) [[likely]] {
152 allocate(s.length());
153
154 assign(s.data(), s.length() + 1);
155
156 wipe(s.data(), s.length());
157 s.clear();
158 } else {
159 set_empty();
160 }
161 }
162
163 /**
164 * Copy constructor.
165 */
167 : data_(AllocatorTraits::select_on_container_copy_construction(
168 ss.allocator())) {
169 if (!ss.empty()) [[likely]] {
170 allocate(ss.length());
171
172 assign(ss.data(), ss.length() + 1);
173 } else {
174 set_empty();
175 }
176 }
177
178 /**
179 * Move constructor.
180 */
181 SecureString(SecureString &&ss) noexcept : data_(std::move(ss.allocator())) {
182 if (!ss.empty()) [[likely]] {
183 set_data(ss.data());
184 set_length(ss.length());
185
186 ss.set_empty();
187 } else {
188 set_empty();
189 }
190 }
191
192 /**
193 * Copies the provided string, wiping its memory.
194 *
195 * @param s String to be copied.
196 */
197 template <class StringTraits = std::char_traits<value_type>,
198 class StringAllocator = std::allocator<value_type>>
201 std::basic_string<value_type, StringTraits, StringAllocator> &&s) {
202 SecureString ss{std::move(s)};
203 swap(ss);
204 return *this;
205 }
206
207 /**
208 * Copy assignment operator.
209 */
211 if (this == std::addressof(ss)) [[unlikely]] {
212 return *this;
213 }
214
215 // need to release the memory before replacing the allocator
216 clear();
217
218 if constexpr (propagate_on_copy()) {
219 allocator() = ss.allocator();
220 }
221
222 if (!ss.empty()) [[likely]] {
223 allocate(ss.length());
224
225 assign(ss.data(), ss.length() + 1);
226 }
227
228 return *this;
229 }
230
231 /**
232 * Move assignment operator.
233 */
235 if (this == std::addressof(ss)) [[unlikely]] {
236 return *this;
237 }
238
239 // need to release the memory before replacing the allocator
240 clear();
241
242 if constexpr (propagate_on_move()) {
243 allocator() = std::move(ss.allocator());
244 }
245
246 if (!ss.empty()) [[likely]] {
247 set_data(ss.data());
248 set_length(ss.length());
249
250 ss.set_empty();
251 }
252
253 return *this;
254 }
255
256 /**
257 * Releases the string, securely wiping the data.
258 */
260
261 /**
262 * Comparison operators.
263 */
264 friend inline bool operator==(const SecureString &l,
265 const SecureString &r) noexcept {
266 return l.length() == r.length() &&
267 !traits_type::compare(l.data(), r.data(), l.length());
268 }
269
270 friend inline bool operator!=(const SecureString &l,
271 const SecureString &r) noexcept {
272 return !(l == r);
273 }
274
275 /**
276 * Provides pointer to the stored string.
277 */
278 [[nodiscard]] inline const_pointer c_str() const noexcept { return data(); }
279
280 /**
281 * Provides length to the stored string.
282 */
283 [[nodiscard]] inline size_type length() const noexcept { return length_; }
284 [[nodiscard]] inline size_type size() const noexcept { return length_; }
285
286 /**
287 * Checks if the stored string is empty.
288 */
289 [[nodiscard]] inline bool empty() const noexcept { return 0 == length(); }
290
291 /**
292 * Swaps the contents of this string with the provided one.
293 *
294 * @param ss String to swap the contents with.
295 */
296 void swap(SecureString &ss) noexcept {
297 if (this == std::addressof(ss)) [[unlikely]] {
298 return;
299 }
300
301 if constexpr (propagate_on_swap()) {
302 using std::swap;
303 swap(allocator(), ss.allocator());
304 }
305
306 {
307 auto ptr = data();
308 set_data(ss.data());
309 ss.set_data(ptr);
310 }
311
312 {
313 auto l = length();
314 set_length(ss.length());
315 ss.set_length(l);
316 }
317 }
318
319 /**
320 * Clears the string, securely wiping the data.
321 */
322 void clear() noexcept {
323 if (empty()) [[unlikely]] {
324 return;
325 }
326
327 wipe(data(), length());
328
329 AllocatorTraits::deallocate(allocator(), data(), length() + 1);
330
331 set_empty();
332 }
333
334 private:
335 // empty-base optimization: http://www.cantrip.org/emptyopt.html
337 explicit constexpr Alloc(const allocator_type &a) : allocator_type(a) {}
338
339 explicit constexpr Alloc(allocator_type &&a = allocator_type())
340 : allocator_type(std::move(a)) {}
341
342 pointer ptr_ = nullptr;
343 };
344
345 static constexpr inline bool propagate_on_copy() noexcept {
347 }
348
349 static constexpr inline bool propagate_on_move() noexcept {
351 }
352
353 static constexpr inline bool propagate_on_swap() noexcept {
355 }
356
357 static inline void wipe(pointer ptr, size_type length) noexcept {
358 secure_wipe(ptr, sizeof(value_type) * length);
359 }
360
361 inline const allocator_type &allocator() const noexcept { return data_; }
362 inline allocator_type &allocator() noexcept { return data_; }
363
364 inline const_pointer data() const noexcept { return data_.ptr_; }
365 inline pointer data() noexcept { return data_.ptr_; }
366
367 inline void set_data(pointer ptr) noexcept { data_.ptr_ = ptr; }
368
369 inline void set_length(size_type length) noexcept { length_ = length; }
370
372 set_data(AllocatorTraits::allocate(allocator(), length + 1));
374 }
375
377 if (1 == length) [[unlikely]] {
378 traits_type::assign(*data(), *ptr);
379 } else {
381 }
382 }
383
384 void set_empty() noexcept {
385 set_data(const_cast<pointer>(&kNull));
386 set_length(0);
387 }
388
389 static constexpr value_type kNull{};
390
393};
394
395} // namespace detail
396
397#ifdef __sun
398// mlock() is a privileged call on Solaris, don't use the SecureAllocator there
400#else // !__sun
403#endif // !__sun
404
405} // namespace mysql_harness
406
407#endif // ROUTER_SRC_HARNESS_INCLUDE_SECURE_STRING_H_
Null-terminated string which is securely wiped on destruction.
Definition: secure_string.h:59
SecureString & operator=(SecureString &&ss) noexcept
Move assignment operator.
Definition: secure_string.h:234
AllocatorTraits::difference_type difference_type
Definition: secure_string.h:69
AllocatorTraits::size_type size_type
Definition: secure_string.h:68
size_type length_
Definition: secure_string.h:392
SecureString() noexcept
Default constructor.
Definition: secure_string.h:80
allocator_type & allocator() noexcept
Definition: secure_string.h:362
void clear() noexcept
Clears the string, securely wiping the data.
Definition: secure_string.h:322
void allocate(size_type length)
Definition: secure_string.h:371
const_pointer data() const noexcept
Definition: secure_string.h:364
friend bool operator!=(const SecureString &l, const SecureString &r) noexcept
Definition: secure_string.h:270
Traits::char_type value_type
Definition: secure_string.h:65
Allocator allocator_type
Definition: secure_string.h:66
AllocatorTraits::pointer pointer
Definition: secure_string.h:74
static void wipe(pointer ptr, size_type length) noexcept
Definition: secure_string.h:357
static constexpr bool propagate_on_swap() noexcept
Definition: secure_string.h:353
static constexpr value_type kNull
Definition: secure_string.h:389
assign(s.data(), s.length()+1)
size_type length() const noexcept
Provides length to the stored string.
Definition: secure_string.h:283
value_type & reference
Definition: secure_string.h:71
SecureString(const allocator_type &alloc) noexcept
Constructor with an allocator.
Definition: secure_string.h:85
const value_type & const_reference
Definition: secure_string.h:72
static constexpr bool propagate_on_copy() noexcept
Definition: secure_string.h:345
void swap(SecureString &ss) noexcept
Swaps the contents of this string with the provided one.
Definition: secure_string.h:296
~SecureString()
Releases the string, securely wiping the data.
Definition: secure_string.h:259
friend bool operator==(const SecureString &l, const SecureString &r) noexcept
Comparison operators.
Definition: secure_string.h:264
SecureString(const SecureString &ss)
Copy constructor.
Definition: secure_string.h:166
Traits traits_type
Definition: secure_string.h:64
SecureString & operator=(std::basic_string< value_type, StringTraits, StringAllocator > &&s)
Copies the provided string, wiping its memory.
Definition: secure_string.h:200
static constexpr bool propagate_on_move() noexcept
Definition: secure_string.h:349
bool empty() const noexcept
Checks if the stored string is empty.
Definition: secure_string.h:289
const_pointer c_str() const noexcept
Provides pointer to the stored string.
Definition: secure_string.h:278
SecureString & operator=(const SecureString &ss)
Copy assignment operator.
Definition: secure_string.h:210
const allocator_type & allocator() const noexcept
Definition: secure_string.h:361
std::allocator_traits< Allocator > AllocatorTraits
Definition: secure_string.h:61
SecureString(pointer ptr, size_type length, const allocator_type &alloc=allocator_type())
Copies the provided string, wiping the memory pointed by ptr.
Definition: secure_string.h:96
void set_data(pointer ptr) noexcept
Definition: secure_string.h:367
AllocatorTraits::const_pointer const_pointer
Definition: secure_string.h:75
void assign(const_pointer ptr, size_type length)
Definition: secure_string.h:376
void set_length(size_type length) noexcept
Definition: secure_string.h:369
SecureString(SecureString &&ss) noexcept
Move constructor.
Definition: secure_string.h:181
Alloc data_
Definition: secure_string.h:391
size_type size() const noexcept
Definition: secure_string.h:284
void set_empty() noexcept
Definition: secure_string.h:384
pointer data() noexcept
Definition: secure_string.h:365
Definition: secure_string.h:45
const char * p
Definition: ctype-mb.cc:1227
constexpr bool likely(bool expr)
Definition: my_compiler.h:57
constexpr bool unlikely(bool expr)
Definition: my_compiler.h:58
static int count
Definition: myisam_ftdump.cc:45
void copy(Shards< COUNT > &dst, const Shards< COUNT > &src) noexcept
Copy the counters, overwrite destination.
Definition: ut0counter.h:354
Definition: fts0fts.cc:238
bool distance(const dd::Spatial_reference_system *srs, const Geometry *g1, const Geometry *g2, double *distance, bool *is_null) noexcept
Computes the distance between two geometries.
Definition: distance.cc:40
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
void HARNESS_EXPORT secure_wipe(void *ptr, std::size_t count)
Definition: secure_string.cc:37
Definition: common.h:44
Definition: gcs_xcom_synode.h:64
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:86
static int compare(size_t a, size_t b)
Function to compare two size_t integers for their relative order.
Definition: rpl_utility.cc:107
static void swap(String &a, String &b) noexcept
Definition: sql_string.h:663
Adapter for SecureMemoryPool which can be used by the STL allocators.
Definition: secure_allocator.h:37
Definition: secure_string.h:336
pointer ptr_
Definition: secure_string.h:342
constexpr Alloc(const allocator_type &a)
Definition: secure_string.h:337
constexpr Alloc(allocator_type &&a=allocator_type())
Definition: secure_string.h:339