这是克洛克的误报吗?

Is this a false positive from Klocwork

本文关键字:洛克      更新时间:2023-10-16

Background

请考虑以下代码:

    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、无符号 int、long 和 unsigned long。不要陷入这个片段的其他问题中,这是关于klocwork的。

此模板化代码是类的一部分,因此它位于头文件中。

如果我缺少其他相关信息,请询问。

问题

在与Klocwork进行分析后,我得到了SV。禁止。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视为内部函数的功能。