mirror of
https://github.com/ETLCPP/etl.git
synced 2026-06-30 22:38:44 +08:00
Merge remote-tracking branch 'origin/feature/secure_strings' into development
This commit is contained in:
commit
50a8b72697
@ -50,6 +50,7 @@ SOFTWARE.
|
||||
#include "error_handler.h"
|
||||
#include "integral_limits.h"
|
||||
#include "exception.h"
|
||||
#include "memory.h"
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "27"
|
||||
@ -229,15 +230,32 @@ namespace etl
|
||||
is_truncated = false;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Sets the 'secure' flag to the requested state.
|
||||
//*************************************************************************
|
||||
void set_secure()
|
||||
{
|
||||
clear_afer_use = true;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Gets the 'secure' state flag.
|
||||
//*************************************************************************
|
||||
bool is_secure() const
|
||||
{
|
||||
return clear_afer_use;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor.
|
||||
//*************************************************************************
|
||||
string_base(size_t max_size_)
|
||||
: is_truncated(false),
|
||||
current_size(0),
|
||||
CAPACITY(max_size_)
|
||||
: is_truncated(false)
|
||||
, clear_afer_use(false)
|
||||
, current_size(0)
|
||||
, CAPACITY(max_size_)
|
||||
{
|
||||
}
|
||||
|
||||
@ -248,9 +266,10 @@ namespace etl
|
||||
{
|
||||
}
|
||||
|
||||
bool is_truncated; ///< Set to true if the operation truncated the string.
|
||||
size_type current_size; ///< The current number of elements in the string.
|
||||
const size_type CAPACITY; ///< The maximum number of elements in the string.
|
||||
bool is_truncated; ///< Set to true if the operation truncated the string.
|
||||
bool clear_afer_use; ///< Set to true if the string must be cleared after use.
|
||||
size_type current_size; ///< The current number of elements in the string.
|
||||
const size_type CAPACITY; ///< The maximum number of elements in the string.
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
@ -531,6 +550,8 @@ namespace etl
|
||||
{
|
||||
is_truncated = true;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
//*********************************************************************
|
||||
@ -1059,6 +1080,7 @@ namespace etl
|
||||
|
||||
current_size -= n_delete;
|
||||
p_buffer[current_size] = 0;
|
||||
cleanup();
|
||||
|
||||
return first;
|
||||
}
|
||||
@ -1383,6 +1405,11 @@ namespace etl
|
||||
// Insert the new stuff.
|
||||
insert(position, str, subposition, sublength);
|
||||
|
||||
if (str.truncated())
|
||||
{
|
||||
is_truncated = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1983,7 +2010,8 @@ namespace etl
|
||||
void initialise()
|
||||
{
|
||||
current_size = 0;
|
||||
p_buffer[0] = 0;
|
||||
cleanup();
|
||||
p_buffer[0] = 0;
|
||||
is_truncated = false;
|
||||
}
|
||||
|
||||
@ -2037,9 +2065,25 @@ namespace etl
|
||||
}
|
||||
}
|
||||
|
||||
// Disable copy construction.
|
||||
//*************************************************************************
|
||||
/// Clear the unused trailing portion of the string.
|
||||
//*************************************************************************
|
||||
void cleanup()
|
||||
{
|
||||
if (is_secure())
|
||||
{
|
||||
etl::memory_clear_range(&p_buffer[current_size], &p_buffer[CAPACITY]);
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Disable copy construction.
|
||||
//*************************************************************************
|
||||
ibasic_string(const ibasic_string&);
|
||||
|
||||
//*************************************************************************
|
||||
/// Pointer to the string's buffer.
|
||||
//*************************************************************************
|
||||
T* p_buffer;
|
||||
|
||||
//*************************************************************************
|
||||
@ -2047,15 +2091,17 @@ namespace etl
|
||||
//*************************************************************************
|
||||
#if defined(ETL_POLYMORPHIC_STRINGS) || defined(ETL_POLYMORPHIC_CONTAINERS)
|
||||
public:
|
||||
virtual ~ibasic_string()
|
||||
{
|
||||
}
|
||||
virtual
|
||||
#else
|
||||
protected:
|
||||
#endif
|
||||
~ibasic_string()
|
||||
{
|
||||
if (is_secure())
|
||||
{
|
||||
initialise();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
//***************************************************************************
|
||||
|
||||
@ -1108,7 +1108,6 @@ namespace etl
|
||||
|
||||
//*****************************************************************************
|
||||
/// A low level function that clears an object's memory to zero.
|
||||
|
||||
///\param p Pointer to the memory.
|
||||
///\param n Size of the memory.
|
||||
///\ingroup memory
|
||||
@ -1128,11 +1127,39 @@ namespace etl
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
void memory_clear(T &object)
|
||||
void memory_clear(volatile T &object)
|
||||
{
|
||||
memory_clear(reinterpret_cast<volatile char*>(&object), sizeof(T));
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// A low level function that clears a range to zero.
|
||||
///\tparam T The type.
|
||||
///\param begin The first object in the range.
|
||||
///\param n The number of objects.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
void memory_clear_range(volatile T* begin, size_t n)
|
||||
{
|
||||
memory_clear(reinterpret_cast<volatile char*>(begin), n * sizeof(T));
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// A low level function that clears a range to zero.
|
||||
///\tparam T The type.
|
||||
///\param begin The first object in the range.
|
||||
///\param end One past the last object in the range.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
void memory_clear_range(volatile T* begin, volatile T* end)
|
||||
{
|
||||
const size_t n = static_cast<size_t>(std::distance(begin, end));
|
||||
|
||||
memory_clear_range(begin, n);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// A low level function that clears an object's memory to zero.
|
||||
///\param p Pointer to the memory.
|
||||
@ -1156,10 +1183,56 @@ namespace etl
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
void memory_set(T &object, char value)
|
||||
void memory_set(volatile T &object, const char value)
|
||||
{
|
||||
memory_set(reinterpret_cast<volatile char*>(&object), sizeof(T), value);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// A low level function that clears a range to zero.
|
||||
///\tparam T The type.
|
||||
///\param begin The first object in the range.
|
||||
///\param n The number of objects.
|
||||
///\param value The value to set the object's memory to.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
void memory_set_range(volatile T* begin, size_t n, const char value)
|
||||
{
|
||||
memory_set(reinterpret_cast<volatile char*>(begin), n * sizeof(T), value);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// A low level function that clears a range to zero.
|
||||
///\tparam T The type.
|
||||
///\param begin The first object in the range.
|
||||
///\param end One past the last object in the range.
|
||||
///\param value The value to set the object's memory to.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
void memory_set_range(volatile T* begin, volatile T* end, const char value)
|
||||
{
|
||||
const size_t n = static_cast<size_t>(std::distance(begin, end));
|
||||
|
||||
memory_set_range(begin, n, value);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
/// Base class for objects that require their memory to be wiped after use.
|
||||
/// Erases the object's memory to zero.
|
||||
/// Note: This may not work for multiply inherited objects.
|
||||
///\tparam T The derived type.
|
||||
///\ingroup memory
|
||||
//*****************************************************************************
|
||||
template <typename T>
|
||||
struct wipe_on_destruct
|
||||
{
|
||||
~wipe_on_destruct()
|
||||
{
|
||||
memory_clear(static_cast<volatile T&>(*this));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -38,8 +38,8 @@ SOFTWARE.
|
||||
///\ingroup utilities
|
||||
|
||||
#define ETL_VERSION_MAJOR 14
|
||||
#define ETL_VERSION_MINOR 22
|
||||
#define ETL_VERSION_PATCH 1
|
||||
#define ETL_VERSION_MINOR 23
|
||||
#define ETL_VERSION_PATCH 0
|
||||
|
||||
#define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) ETL_STRINGIFY(ETL_VERSION_MINOR) ETL_STRINGIFY(ETL_VERSION_PATCH)
|
||||
#define ETL_VERSION_W ETL_WIDE_STRING(ETL_CONCAT(ETL_CONCAT(ETL_VERSION_MAJOR, ETL_VERSION_MINOR), ETL_VERSION_PATCH))
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
===============================================================================
|
||||
14.23.0
|
||||
Added an optional secure mode to strings so that unused space will be cleared to zero
|
||||
and also cleared on destruction.
|
||||
|
||||
===============================================================================
|
||||
14.22.1
|
||||
Modified memory functions so that they will not be optimised away.
|
||||
|
||||
@ -546,6 +546,52 @@ namespace
|
||||
CHECK_EQUAL(0x00, data.d2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_memory_clear_range_pointer_n)
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
uint32_t d1;
|
||||
char d2;
|
||||
};
|
||||
|
||||
Data data[3] = { { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) } };
|
||||
|
||||
etl::memory_clear_range(data, 3);
|
||||
|
||||
CHECK_EQUAL(0x00000000, data[0].d1);
|
||||
CHECK_EQUAL(0x00, data[0].d2);
|
||||
|
||||
CHECK_EQUAL(0x00000000, data[1].d1);
|
||||
CHECK_EQUAL(0x00, data[1].d2);
|
||||
|
||||
CHECK_EQUAL(0x00000000, data[2].d1);
|
||||
CHECK_EQUAL(0x00, data[2].d2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_memory_clear_range_pointer_pointer)
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
uint32_t d1;
|
||||
char d2;
|
||||
};
|
||||
|
||||
Data data[3] = { { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) } };
|
||||
|
||||
etl::memory_clear_range(std::begin(data), std::end(data));
|
||||
|
||||
CHECK_EQUAL(0x00000000, data[0].d1);
|
||||
CHECK_EQUAL(0x00, data[0].d2);
|
||||
|
||||
CHECK_EQUAL(0x00000000, data[1].d1);
|
||||
CHECK_EQUAL(0x00, data[1].d2);
|
||||
|
||||
CHECK_EQUAL(0x00000000, data[2].d1);
|
||||
CHECK_EQUAL(0x00, data[2].d2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_memory_set)
|
||||
{
|
||||
@ -562,5 +608,51 @@ namespace
|
||||
CHECK_EQUAL(0x5A5A5A5A, data.d1);
|
||||
CHECK_EQUAL(0x5A, data.d2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_memory_set_range_pointer_n)
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
uint32_t d1;
|
||||
char d2;
|
||||
};
|
||||
|
||||
Data data[3] = { { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) } };
|
||||
|
||||
etl::memory_set_range(data, 3, 0x5A);
|
||||
|
||||
CHECK_EQUAL(0x5A5A5A5A, data[0].d1);
|
||||
CHECK_EQUAL(0x5A, data[0].d2);
|
||||
|
||||
CHECK_EQUAL(0x5A5A5A5A, data[1].d1);
|
||||
CHECK_EQUAL(0x5A, data[1].d2);
|
||||
|
||||
CHECK_EQUAL(0x5A5A5A5A, data[2].d1);
|
||||
CHECK_EQUAL(0x5A, data[2].d2);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST(test_memory_set_range_pointer_pointer)
|
||||
{
|
||||
struct Data
|
||||
{
|
||||
uint32_t d1;
|
||||
char d2;
|
||||
};
|
||||
|
||||
Data data[3] = { { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) }, { 0xFFFFFFFF, char(0xFF) } };
|
||||
|
||||
etl::memory_set_range(std::begin(data), std::end(data), 0x5A);
|
||||
|
||||
CHECK_EQUAL(0x5A5A5A5A, data[0].d1);
|
||||
CHECK_EQUAL(0x5A, data[0].d2);
|
||||
|
||||
CHECK_EQUAL(0x5A5A5A5A, data[1].d1);
|
||||
CHECK_EQUAL(0x5A, data[1].d2);
|
||||
|
||||
CHECK_EQUAL(0x5A5A5A5A, data[2].d1);
|
||||
CHECK_EQUAL(0x5A, data[2].d2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -3651,5 +3651,90 @@ namespace
|
||||
text.clear_truncated();
|
||||
CHECK(!text.truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_destructor)
|
||||
{
|
||||
char buffer[sizeof(Text)];
|
||||
std::fill_n(buffer, sizeof(Text), 0);
|
||||
::new (buffer) Text(STR("ABCDEF"));
|
||||
|
||||
Text& text = *reinterpret_cast<Text*>(buffer);
|
||||
text.set_secure();
|
||||
|
||||
CHECK(Text(STR("ABCDEF")) == text);
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
// Destroy the text object.
|
||||
text.~Text();
|
||||
|
||||
// Check there no non-zero values in the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_assign)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.assign(STR("ABC"));
|
||||
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_erase)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.erase(pb + 2, pb + 5);
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_replace)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.replace(pb + 1, pb + 4, STR("G"));
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_clear)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.clear();
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -3650,5 +3650,90 @@ namespace
|
||||
text.clear_truncated();
|
||||
CHECK(!text.truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_destructor)
|
||||
{
|
||||
char buffer[sizeof(Text)];
|
||||
std::fill_n(buffer, sizeof(Text), 0);
|
||||
::new (buffer) Text(STR("ABCDEF"));
|
||||
|
||||
Text& text = *reinterpret_cast<Text*>(buffer);
|
||||
text.set_secure();
|
||||
|
||||
CHECK(Text(STR("ABCDEF")) == text);
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
// Destroy the text object.
|
||||
text.~Text();
|
||||
|
||||
// Check there no non-zero values in the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_assign)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.assign(STR("ABC"));
|
||||
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_erase)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.erase(pb + 2, pb + 5);
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_replace)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.replace(pb + 1, pb + 4, STR("G"));
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_clear)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.clear();
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -3650,5 +3650,90 @@ namespace
|
||||
text.clear_truncated();
|
||||
CHECK(!text.truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_destructor)
|
||||
{
|
||||
char buffer[sizeof(Text)];
|
||||
std::fill_n(buffer, sizeof(Text), 0);
|
||||
::new (buffer) Text(STR("ABCDEF"));
|
||||
|
||||
Text& text = *reinterpret_cast<Text*>(buffer);
|
||||
text.set_secure();
|
||||
|
||||
CHECK(Text(STR("ABCDEF")) == text);
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
// Destroy the text object.
|
||||
text.~Text();
|
||||
|
||||
// Check there no non-zero values in the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_assign)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.assign(STR("ABC"));
|
||||
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_erase)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.erase(pb + 2, pb + 5);
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_replace)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.replace(pb + 1, pb + 4, STR("G"));
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_clear)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.clear();
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -3650,5 +3650,90 @@ namespace
|
||||
text.clear_truncated();
|
||||
CHECK(!text.truncated());
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_destructor)
|
||||
{
|
||||
char buffer[sizeof(Text)];
|
||||
std::fill_n(buffer, sizeof(Text), 0);
|
||||
::new (buffer) Text(STR("ABCDEF"));
|
||||
|
||||
Text& text = *reinterpret_cast<Text*>(buffer);
|
||||
text.set_secure();
|
||||
|
||||
CHECK(Text(STR("ABCDEF")) == text);
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
// Destroy the text object.
|
||||
text.~Text();
|
||||
|
||||
// Check there no non-zero values in the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_assign)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.assign(STR("ABC"));
|
||||
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_erase)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.erase(pb + 2, pb + 5);
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_replace)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.replace(pb + 1, pb + 4, STR("G"));
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(text.end(), pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
TEST_FIXTURE(SetupFixture, test_secure_after_clear)
|
||||
{
|
||||
Text text;
|
||||
text.set_secure();
|
||||
text.assign(STR("ABCDEF"));
|
||||
|
||||
Text::pointer pb = text.begin();
|
||||
Text::pointer pe = text.end();
|
||||
|
||||
text.clear();
|
||||
|
||||
// Check there no non-zero values in the remainder of the string.
|
||||
CHECK(std::find_if(pb, pe, [](Text::value_type x) { return x != 0; }) == pe);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user