Отклонение покрытия: - просчет длины строки (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? Я не вижу, в чем здесь проблема, поэтому я не уверен в этом решении и / или его необходимости.

Дополнительная информация такова, что &((my_type*) *my_variable)->Param2.body[1] (просто &Param2.body[1]) будет скопирован в body с помощью strcpy, лайк:

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

3 ответа

Решение

Я пришел к такому выводу, что rici был верен. Учитывая следующее моделирование:

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

typedef struct Param2{
    char* body;
}Param2;

int main()
{
    Param2 test;
    test.body = "test_string\0";
    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-й такой же, как 1-й). Выделенная память видна на изображении выше для всех случаев. Теперь, если мы хотим скопировать исходную строку из байта 2. (&body[1]), это будет означать 10 байтов данных в примере. И согласно документации strcpy:

Чтобы избежать переполнений, размер массива, указанного адресатом, должен быть достаточно длинным, чтобы содержать ту же строку C, что и источник (включая завершающий нулевой символ), и не должен перекрываться в памяти с источником.

Нам нужен еще один для нулевого завершения, дающего нам 11 байтов для выделения. Coverity считает, что мы выделяем 10 байтов, и предлагаем выделить 12.

Но, как мы видим, исходный код выделяет 11 байтов, что является точным количеством байтов, которое нам здесь нужно, поэтому покрытие скрывает ложное срабатывание.

Нет, ...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(...)

Я думаю, что укрытие беспокоится, потому что вы хотите взять strlen из индекса 1 вместо индекса 0. 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]

как предложено прикрытием

Другие вопросы по тегам