Coverity 偏转:- 字符串长度计算错误 (BAD_ALLOC_STRLEN)

Coverity deflect: - String length miscalculation (BAD_ALLOC_STRLEN)

我有一个隐蔽偏转需要修复,但我不确定。我有一个函数 (void my_function(a_type *my_variable)),其中包含以下有问题的代码行:

body = malloc(strlen(&((my_type*) *my_variable)->Param2.body[1]) +1);

其中 body 是一个 unsigned char*

Coverity 消息:

String length miscalculation (BAD_ALLOC_STRLEN)
Using "strlen(((my_type *)*my_variable)->Param2.body + 1)" 
instead of "strlen(((my_type *)*my_variable)->Param2.body) + 1" 
as an argument to "malloc" might be an under-allocation.

现在,给定 strlen 函数调用,如下所示:

strlen(&((my_type*) *my_variable)->Param2.body[1])

并且这一行等同于:

strlen(&((my_type*) *my_variable)->Param2.body + 1)

所以这应该根据消息进行更改,结果将是:

body = malloc((strlen(&((my_type*) *my_variable)->Param2.body)+1) +1);

为什么 malloc 这样的论点不好?我看不出这里的实际问题是什么,所以我不确定这个解决方案 and/or 它的必要性。

其他信息是,&((my_type*) *my_variable)->Param2.body[1](简称 &Param2.body[1])将使用 strcpy 复制到 body,例如:

strcpy(body, &((my_type *) *my_variable)->Param2.body[1]);

不,...body[1]...body + 1 相同。第一个类型是 body 数组的元素类型,第二个类型是 ptr-to-element-type。再读一遍你的 C 书:-)

Coverity 试图告诉您您犯了与

中相同的错误
char foo[42];
/* write a string to foo */
bar = malloc (strlen(foo + 1)); /* which is strlen(&foo[1]) */

当正确的代码是

bar = malloc (strlen(foo) + 1);

我想你误解了括号。

覆盖建议中的+ 1外面 strlen(...)

我认为 Coverity 会担心,因为您想从索引 1 而不是索引 0 中获取 strlen。Coverity 期望索引 0 作为起点 - 如:

body = malloc(strlen(&((my_type*) *my_variable)->Param2.body[0]) +1);
                                                             ^

这也是

body = malloc(strlen(((my_type*) *my_variable)->Param2.body) +1);
              ^                                            ^
            No & operator                                No [0]

如 coverity 所建议

我得出的结论是 @rici 是正确的。考虑以下模拟:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct Param2{
    char* body;
}Param2;

int main()
{
    Param2 test;
    test.body = "test_string[=10=]";
    printf("%s, size: %d + 1 terminating null\n\n",test.body, strlen(test.body));

    printf("original:                %d \n", (strlen(&test.body[1]) + 1));
    printf("what coverity thinks:    %d \n", strlen(test.body + 1));
    printf("what coverity suggests:  %d \n", (strlen(test.body) + 1));
    printf("a more transparent way:  %d \n\n", (strlen(test.body + 1) + 1));

    return 1;
}

这是输出:

一共有三种情况(第4种与第一种相同)。在所有情况下,都可以在上图中看到分配的内存。现在,如果我们想从 2.byte (&body[1]) 复制源字符串,这意味着示例中有 10 个字节的数据。并根据 strcpy documentation:

To avoid overflows, the size of the array pointed by destination shall be long enough to contain the same C string as source (including the terminating null character), and should not overlap in memory with source.

我们还需要一个空终止符,这样我们就可以分配 11 个字节。 Coverity认为我们分配10个字节,建议分配12个。

但是正如我们所见,原始代码分配了 11 个字节,这正是我们在这里需要的字节数,这使得覆盖度偏离了误报。