Правильный способ обнуления объекта AnsiString

Как обнулить объект AnsiString? Например:

void TesteClass::test()
{
    AnsiString cardNumber = "1234567890123456";
    ..
}

Объект AnsiString уничтожается автоматически, но его внутренние данные не очищаются, поэтому средство считывания памяти может считывать информацию. Нам нужно обнулить эти данные, чтобы конфиденциальная информация не попала в память.

Класс AnsiString имеет метод c_str() для прямого доступа к внутренним данным, но делать что-то подобное не рекомендуется:

memset(cardNumber.c_str(), 0, cardNumber.Length());

Как правильно обнулить внутренние данные AnsiString до уничтожения объекта?

1 ответ

Решение

Там нет ничего плохого в использовании memset() как вы показали. С помощью c_str() таким образом, является правильным (до тех пор, пока вы не превышаете Length(), поскольку c_str() возвращает указатель на постоянную память, если AnsiString пусто):

void TesteClass::test()
{
    AnsiString cardNumber = "1234567890123456";
    // ...
    memset(cardNumber.c_str(), 0, cardNumber.Length());
}

Поскольку вас беспокоит утечка информации, рассмотрите возможность использования SecureZeroMemory() вместо memset() (см. в чем смысл SecureZeroMemory?).

Чтобы автоматизировать обнуление (так что вам не нужно это делать), подумайте об упаковке AnsiString в стиле RAII class / struct (вы не можете извлечь из AnsiString напрямую, RTL не позволяет), чей деструктор выполняет обнуление, а затем использует это class / struct где необходимо вместо использования AnsiString непосредственно.

Просто будь осторожен, так как AnsiString использует данные с подсчетом ссылок, поэтому не обнуляйте данные, если ваш AnsiString это единственный экземпляр, ссылающийся на данные:

class SaferAnsiString
{
private:
    AnsiString m_Str;

    void CheckZeroNeeded()
    {
        // AnsiString gained a public RefCount() method in C++Builder 2009.
        // In earlier versions, access the reference count manually...
        #ifdef _DELPHI_STRING_UNICODE
        if (m_Str.RefCount() == 1)
        #else
        const void *data = m_Str.data();
        if ((data) && (static_cast<const int*>(data)[-2] == 1))
        #endif
            SecureZeroMemory(m_Str.c_str(), m_Str.Length());
    }

public:
    SaferAnsiString(const AnsiString &src = AnsiString())
        : m_Str(src)
    {
    }

    ~SaferAnsiString()
    {
        CheckZeroNeeded();
    }

    SaferAnsiString& operator=(const AnsiString &rhs)
    {
        CheckZeroNeeded();
        m_Str = rhs;
        return *this;
    }

    operator AnsiString () const { return m_Str; }

    // other methods as needed...
};

void TesteClass::test()
{
    SaferAnsiString cardNumber = "1234567890123456";
    // ...
}
Другие вопросы по тегам