Skip to content

Commit d57c64c

Browse files
author
Christopher Dawes
committed
Unit test for secure allocator and tests for secure destruction
1 parent 7218948 commit d57c64c

File tree

4 files changed

+62
-13
lines changed

4 files changed

+62
-13
lines changed

include/json/allocator.h

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
66
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
77

8+
#include <algorithm> //std::filln
89
#include <cstring> // std::memset
910
#include <cstddef> // std::size_t, std::ptrdiff_t
1011
#include <utility> // std::forward
@@ -33,16 +34,47 @@ class JSON_API SecureAllocator {
3334
using difference_type = std::ptrdiff_t;
3435

3536
/**
36-
* Release memory which was allocated for N items at pointer P.
37-
*
38-
* The memory block is filled with zeroes before being released.
39-
* The pointer argument is tagged as "volatile" to prevent the
40-
* compiler optimizing out this critical step.
41-
*/
42-
void deallocate(volatile pointer p, size_type n) {
43-
std::fill_n((volatile char*)p, n * sizeof(value_type), 0);
44-
std::allocator<T>::deallocate(p, n);
45-
}
37+
* Allocate memory for N items using the standard allocator.
38+
*/
39+
pointer allocate(size_type n) {
40+
// allocate using "global operator new"
41+
return static_cast<pointer>(::operator new(n * sizeof(T)));
42+
}
43+
44+
/**
45+
* Release memory which was allocated for N items at pointer P.
46+
*
47+
* The memory block is filled with zeroes before being released.
48+
* The pointer argument is tagged as "volatile" to prevent the
49+
* compiler optimizing out this critical step.
50+
*/
51+
void deallocate(volatile pointer p, size_type n) {
52+
std::fill_n((volatile char*)p, n * sizeof(value_type), 0);
53+
// free using "global operator delete"
54+
::operator delete(p);
55+
}
56+
57+
/**
58+
* Construct an item in-place at pointer P.
59+
*/
60+
template<typename... Args>
61+
void construct(pointer p, Args&&... args) {
62+
// construct using "placement new" and "perfect forwarding"
63+
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
64+
}
65+
66+
/**
67+
* Destroy an item in-place at pointer P.
68+
*/
69+
void destroy(pointer p) {
70+
// destroy using "explicit destructor"
71+
p->~T();
72+
}
73+
74+
// Boilerplate
75+
SecureAllocator() {}
76+
template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
77+
template<typename U> struct rebind { using other = SecureAllocator<U>; };
4678
};
4779

4880
template<typename T, typename U>

include/json/json.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifndef JSON_JSON_H_INCLUDED
77
#define JSON_JSON_H_INCLUDED
88

9+
#include "allocator.h"
910
#include "autolink.h"
1011
#include "value.h"
1112
#include "reader.h"

include/json/writer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ std::basic_string<char, _Traits, _Alloc> valueToQuotedStringN(const char* value,
6262
// sequence from occurring.
6363
default:
6464
if ((WriterUtils::isControlCharacter(*c)) || (*c == 0)) {
65-
std::ostringstream oss;
65+
std::basic_ostringstream<char, _Traits, _Alloc> oss;
6666
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
6767
<< std::setw(4) << static_cast<int>(*c);
6868
result += oss.str();
@@ -201,7 +201,7 @@ std::basic_string<char, _Traits, _Alloc> valueToQuotedString(const char* value)
201201
// sequence from occurring.
202202
default:
203203
if (WriterUtils::isControlCharacter(*c)) {
204-
std::ostringstream oss;
204+
std::basic_ostringstream<char, _Traits, _Alloc> oss;
205205
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
206206
<< std::setw(4) << static_cast<int>(*c);
207207
result += oss.str();
@@ -241,7 +241,7 @@ std::basic_string<char, _Traits, _Alloc> JSON_API writeString(typename StreamWri
241241
#else
242242
typedef std::auto_ptr<StreamWriter<_Traits, _Alloc>> StreamWriterPtr;
243243
#endif
244-
std::ostringstream sout;
244+
std::basic_ostringstream<char, _Traits, _Alloc> sout;
245245
StreamWriterPtr const writer(builder.newStreamWriter());
246246
writer->write(root, &sout);
247247
return sout.str();

src/test_lib_json/main.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,20 @@ JSONTEST_FIXTURE(RValueTest, moveConstruction) {
25192519
#endif
25202520
}
25212521

2522+
struct TestSecureAllocator : JsonTest::TestCase {};
2523+
2524+
JSONTEST_FIXTURE(TestSecureAllocator, secureDestruction) {
2525+
using TestSecureValue = Json::Value<std::char_traits<char>, Json::SecureAllocator<char>>;
2526+
2527+
TestSecureValue myValue;
2528+
myValue["foo"] = "bar baz";
2529+
JSONTEST_ASSERT_EQUAL(Json::stringValue, myValue["foo"]);
2530+
JSONTEST_ASSERT_EQUAL(TestSecureValue("bar baz"), myValue["foo"]);
2531+
2532+
myValue["bar"] = 1234;
2533+
JSONTEST_ASSERT_EQUAL(TestSecureValue(1234), myValue["bar"]);
2534+
}
2535+
25222536
int main(int argc, const char* argv[]) {
25232537
JsonTest::Runner runner;
25242538
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
@@ -2594,5 +2608,7 @@ int main(int argc, const char* argv[]) {
25942608

25952609
JSONTEST_REGISTER_FIXTURE(runner, RValueTest, moveConstruction);
25962610

2611+
JSONTEST_REGISTER_FIXTURE(runner, TestSecureAllocator, secureDestruction);
2612+
25972613
return runner.runCommandLine(argc, argv);
25982614
}

0 commit comments

Comments
 (0)