2017-07-21 03:44:36 -07:00
|
|
|
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
2016-03-06 11:42:11 -06:00
|
|
|
// Distributed under MIT license, or public domain if desired and
|
|
|
|
// recognized in your jurisdiction.
|
|
|
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
|
|
|
|
2019-11-14 09:38:11 -08:00
|
|
|
#ifndef JSON_ALLOCATOR_H_INCLUDED
|
|
|
|
#define JSON_ALLOCATOR_H_INCLUDED
|
2016-03-06 11:42:11 -06:00
|
|
|
|
2024-09-12 07:43:25 +07:00
|
|
|
#include <algorithm>
|
2016-03-06 11:42:11 -06:00
|
|
|
#include <cstring>
|
|
|
|
#include <memory>
|
|
|
|
|
Use default rather than hard-coded 8 for maximum aggregate member alignment (#1378)
On CHERI, and thus Arm's Morello prototype, pointers are represented as
hardware capabilities. These capabilities are comprised of not just an
integer address, as is the representation for traditional pointers, but
also bounds, permissions and other metadata, plus a tag bit used as the
validity bit, which provides fine-grained spatial and referential safety
for C and C++ in hardware. This tag bit is not part of the data itself
and is instead kept on the side, flowing with the capability between
registers and the memory subsystem, and any attempt to amplify the
privilege of or corrupt a capability clears this tag (or, in some cases,
traps), rendering them impossible to forge; you can only create
capabilities that are (possibly trivial) subsets of existing ones.
When the capability is stored in memory, this tag bit needs to be
preserved, which is done through the use of tagged memory. Every
capability-sized word gains an additional non-addressable (from the
CPU's perspective; depending on the implementation the tag bits may be
stored in a small block of memory carved out of normal DRAM that the CPU
is blocked from accessing) bit. This means that capabilities can only be
stored to aligned locations; attempting to store them to unaligned
locations will trap with an alignment fault or, if you end up using a
memcpy call, will copy the raw bytes of the capability's representation
but lose the tag, so when it is eventually loaded back as a capability
and dereferenced it will fault.
Since, on 64-bit architectures, our capabilities, used to implement C
language pointers, are 128-bit quantities, this means they need 16-byte
alignment. Currently the various #pragma pack directives, used to work
around (extremely broken and bogus) code that includes jsoncpp in a
context where the maximum alignment has been overridden, hard-code 8 as
the maximum alignment to use, and so do not sufficiently align CHERI /
Morello capabilities on 64-bit architectures. On Windows x64, the
default is also not 8 but 16 (ARM64 is supposedly 8), so this is
slightly dodgy to do there too, but in practice likely not an issue so
long as you don't use any 128-bit types there.
Instead of hard-coding a width, use a directive that resets the packing
back to the default. Unfortunately, whilst GCC and Clang both accept
using #pragma pack(push, 0) as shorthand like for any non-zero value,
MSVC does not, so this needs to be two directives.
2022-01-12 21:27:16 +00:00
|
|
|
#pragma pack(push)
|
|
|
|
#pragma pack()
|
2016-12-03 22:29:14 +02:00
|
|
|
|
2016-03-06 11:42:11 -06:00
|
|
|
namespace Json {
|
2018-05-20 16:55:27 -04:00
|
|
|
template <typename T> class SecureAllocator {
|
|
|
|
public:
|
|
|
|
// Type definitions
|
|
|
|
using value_type = T;
|
|
|
|
using pointer = T*;
|
|
|
|
using const_pointer = const T*;
|
|
|
|
using reference = T&;
|
|
|
|
using const_reference = const T&;
|
|
|
|
using size_type = std::size_t;
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Allocate memory for N items using the standard allocator.
|
|
|
|
*/
|
|
|
|
pointer allocate(size_type n) {
|
|
|
|
// allocate using "global operator new"
|
|
|
|
return static_cast<pointer>(::operator new(n * sizeof(T)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Release memory which was allocated for N items at pointer P.
|
|
|
|
*
|
|
|
|
* The memory block is filled with zeroes before being released.
|
|
|
|
*/
|
2020-10-13 17:55:58 +02:00
|
|
|
void deallocate(pointer p, size_type n) {
|
2024-09-12 07:43:25 +07:00
|
|
|
// These constructs will not be removed by the compiler during optimization,
|
|
|
|
// unlike memset.
|
|
|
|
#if defined(HAVE_MEMSET_S)
|
2020-10-13 17:55:58 +02:00
|
|
|
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
2024-09-12 07:43:25 +07:00
|
|
|
#elif defined(_WIN32)
|
|
|
|
RtlSecureZeroMemory(p, n * sizeof(T));
|
|
|
|
#else
|
|
|
|
std::fill_n(reinterpret_cast<volatile unsigned char*>(p), n, 0);
|
|
|
|
#endif
|
|
|
|
|
2018-05-20 16:55:27 -04:00
|
|
|
// free using "global operator delete"
|
|
|
|
::operator delete(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct an item in-place at pointer P.
|
|
|
|
*/
|
|
|
|
template <typename... Args> void construct(pointer p, Args&&... args) {
|
|
|
|
// construct using "placement new" and "perfect forwarding"
|
|
|
|
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_type max_size() const { return size_t(-1) / sizeof(T); }
|
|
|
|
|
|
|
|
pointer address(reference x) const { return std::addressof(x); }
|
|
|
|
|
|
|
|
const_pointer address(const_reference x) const { return std::addressof(x); }
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Destroy an item in-place at pointer P.
|
|
|
|
*/
|
|
|
|
void destroy(pointer p) {
|
|
|
|
// destroy using "explicit destructor"
|
|
|
|
p->~T();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Boilerplate
|
|
|
|
SecureAllocator() {}
|
|
|
|
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
2024-09-09 15:48:18 -07:00
|
|
|
template <typename U> struct rebind {
|
|
|
|
using other = SecureAllocator<U>;
|
|
|
|
};
|
2016-03-06 11:42:11 -06:00
|
|
|
};
|
|
|
|
|
2018-05-20 16:55:27 -04:00
|
|
|
template <typename T, typename U>
|
2016-03-06 11:42:11 -06:00
|
|
|
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
2018-05-20 16:55:27 -04:00
|
|
|
return true;
|
2016-03-06 11:42:11 -06:00
|
|
|
}
|
|
|
|
|
2018-05-20 16:55:27 -04:00
|
|
|
template <typename T, typename U>
|
2016-03-06 11:42:11 -06:00
|
|
|
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
2018-05-20 16:55:27 -04:00
|
|
|
return false;
|
2016-03-06 11:42:11 -06:00
|
|
|
}
|
|
|
|
|
2018-05-20 16:55:27 -04:00
|
|
|
} // namespace Json
|
2016-03-06 11:42:11 -06:00
|
|
|
|
2016-12-03 22:29:14 +02:00
|
|
|
#pragma pack(pop)
|
|
|
|
|
2019-11-14 09:38:11 -08:00
|
|
|
#endif // JSON_ALLOCATOR_H_INCLUDED
|