Для получения триального ключа
заполните форму ниже
Team License (базовая версия)
Enterprise License (расширенная версия)
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
GBP
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

** На сайте установлена reCAPTCHA и применяются
Политика конфиденциальности и Условия использования Google.
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте папку
Spam/Junk и нажмите на письме кнопку "Не спам".
Так Вы не пропустите ответы от нашей команды.

>
>
>
V597. The compiler could delete the 'me…
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Диагностика микро-оптимизаций (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Cтандарт MISRA
Стандарт AUTOSAR
Дополнительная информация
Оглавление

V597. The compiler could delete the 'memset' function call, which is used to flush 'Foo' buffer. The RtlSecureZeroMemory() function should be used to erase the private data.

7 декабря 2012 г.

Анализатор обнаружил потенциальную ошибку, когда массив, содержащий приватную информацию, не будет очищен.

Рассмотрим пример кода.

void Foo()
{
  char password[MAX_PASSWORD_LEN];
  InputPassword(password);
  ProcessPassword(password);
  memset(password, 0, sizeof(password));
}

Функция на стеке создает временный буфер, предназначенный для хранения пароля. По окончанию работы с паролем, мы хотим очистить этот буфер. Если это не сделать, пароль останется в памяти, что может привести к неприятным последствиям. На эту тему есть хорошая статья "Перезаписывать память - зачем?".

К сожалению, приведенный код может оставить буфер неочищенным. Обратите внимание, что массив 'password' очищается в конце и более не используется. Поэтому при сборке Release версии программы, компилятор, скорее всего, удалит вызов функции memset(). На это компилятор имеет полное право. Такое изменение не влияет на наблюдаемое поведение, которое описано в Стандарте как последовательность вызова функций ввода-вывода и чтения-записи volatile данных. То есть с точки зрения языка Си/Си++, если удалить вызов функции memset(), это ничего не изменит!

Для очистки буферов содержащих приватную информацию необходимо использовать специальную функцию RtlSecureZeroMemory или memset_s (см. также статью "Безопасная очистка приватных данных").

Исправленный вариант кода:

void Foo()
{
  char password[MAX_PASSWORD_LEN];
  InputPassword(password);
  ProcessPassword(password);
  RtlSecureZeroMemory(password, sizeof(password));
}

Кажется, что на практике, компилятор не может удалить вызов такой важной функции memset(). Может возникнуть впечатление, что речь идет о редких экзотических компиляторах. Нет, это не так. Возьмем для примера компилятор Visual C++ 10, входящий в состав Visual Studio 2010.

Рассмотрим две функции.

void F1()
{
  TCHAR buf[100];
  _stprintf(buf, _T("Test: %d"), 123);
  MessageBox(NULL, buf, NULL, MB_OK);
  memset(buf, 0, sizeof(buf));
}

void F2()
{
  TCHAR buf[100];
  _stprintf(buf, _T("Test: %d"), 123);
  MessageBox(NULL, buf, NULL, MB_OK);
  RtlSecureZeroMemory(buf, sizeof(buf));
}

Функции отличаются тем, как они очищают буфер. Первая использует функцию memset(), а вторая RtlSecureZeroMemory(). Скомпилируем оптимизированный код, указав для компилятора Visual C++ 10 ключ "/O2". Рассмотрим получившийся ассемблерный код:

V597_ru/image1.png

Рисунок 1. Функция memset() удалена.

V597_ru/image2.png

Рисунок 2. Функция RtlSecureZeroMemory() заполняет память нулями.

Как видно в ассемблерном коде, функция memset() была удалена компилятором при оптимизации. Функция RtlSecureZeroMemory() выстроилась в код, поэтому теперь массив успешно обнуляется.

Дополнительные ссылки:

Данная диагностика классифицируется как:

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V597.

Этот сайт использует куки и другие технологии, чтобы предоставить вам более персонализированный опыт. Продолжая просмотр страниц нашего веб-сайта, вы принимаете условия использования этих файлов. Если вы не хотите, чтобы ваши данные обрабатывались, пожалуйста, покиньте данный сайт. Подробнее →
Принять