Отклонение покрытия: - просчет длины строки (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]
как предложено прикрытием