Фон
Рассмотрим следующий код:
template <typename T>
void WriteData(const size_t &offset, const T &data)
{
if(sizeof(data) <= 8) //if size is 64bits or less, memcpy is not as efficient as a direct write
*reinterpret_cast<T*>(reinterpret_cast<char*>(_memView) + offset) = data;
else
{
errno_t result = memcpy_s(reinterpret_cast<char*>(_memView) + offset, SHARED_BUFFER_SIZE - offset, &data, sizeof(data));
if(result != 0)
throw exception("Error writing data");
}
}
Предположим, что _memView объявлен как пустой указатель.
memcpy_s нигде не был переопределен.
Функция создается только со следующими типами: char, int, HANDLE, unsigned int, long и unsigned long. Не увязайте в других проблемах с этим фрагментом, речь идет о klocwork.
Этот шаблонный код является частью класса, и поэтому он находится в заголовочном файле.
Если мне не хватает другой подходящей информации, просто спросите.
Проблема
После анализа с помощью Klocwork я получаю предупреждение SV.BANNED.COPY: «Не используйте небезопасные функции буферного копирования — рассмотрите возможность использования безопасного варианта, такого как strcpy_s»
Итак, я делаю что-то мертвое здесь с тем, как я называю memcpy_s, memcpy_s считается небезопасным для Klocwork? Смущает ли Klocwork приведение к char * и думает, что я манипулирую строкой в стиле C?
Я хотел бы понять, что Klocwork пытается сказать мне, даже если он просто говорит мне, что это ложный позитив.
Эта функция не работает, согласно стандарту C ++.
if
ветки выполняют запись без выравнивания и нарушают строгое псевдонимы.Обе ветви с радостью запишут конец вашего буфера.
if
ветка вообще не проверяет размер.else
ветвь подчиняется беззнаковому переносу в расчете аргумента размера буфера.memcpy_s
не панацея С помощью memcpy
и некоторые размышления о проверке параметров будут бить вслепую memcpy_s
каждый раз.
Исправленная версия:
template <typename T>
void WriteData(const size_t &offset, const T &data)
{
if (sizeof data > SHARED_BUFFER_SIZE)
throw exception("Type cannot fit in shared buffer");
if (offset > SHARED_BUFFER_SIZE - sizeof data)
throw exception("Copy would overrun end of shared buffer");
memcpy(reinterpret_cast<char*>(_memView) + offset, &data, sizeof data);
}
Чтобы эффективно обрабатывать небольшие копии, убедитесь, что ваш компилятор обрабатывает memcpy
как встроенный включен.