这是Klocwork的误报

时间:2014-08-21 13:49:56

标签: c++ templates memcpy klocwork

背景

请考虑以下代码:

    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被声明为void指针。 memcpy_s尚未在任何地方重新定义。

该函数仅使用以下类型实例化:char,int,HANDLE,unsigned int,long和unsigned long。不要陷入这个片段的其他问题,这是关于klocwork。

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

如果我错过了其他相关信息,请问。

问题

用Klocwork分析后,我收到SV.BANNED.COPY警告:“不要使用不安全的缓冲区复制功能 - 考虑使用安全的变体,如strcpy_s”

所以我在这里做脑死亡的方式我正在调用memcpy_s,是不是被Klocwork认为是不安全的memcpy? Klocwork是否被铸造混淆为char *并且认为我正在操纵C风格的字符串?

我想了解Klocwork试图告诉我什么,即使它只是告诉我这是误报。

1 个答案:

答案 0 :(得分:2)

根据标准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作为内在函数的处理。