Это действительно переполнение буфера?

Инструмент статического анализа, который мы используем, помечает код C, как показано ниже, как критическое переполнение буфера.

#define size 64
char  buf [size + 1] = "";
memset (buf, 0, size + 1);

Сообщение об ошибке инструмента: Переполнение буфера (индекс массива выходит за границы): размер массива 'buf' равен 1. Массив 'buf' может использовать индекс 0..64.

Это законно? Действительно ли присваивание массива символов пустой строке приводит к уменьшению ее длины до одного байта, как если бы она была определена как char buf [] = "";?


person An̲̳̳drew    schedule 16.02.2009    source источник
comment
Оказывается, это будет в C99, видимо. Виноват. :)   -  person Randolpho    schedule 16.02.2009
comment
Вы должны удалить точку с запятой из определения size.   -  person bk1e    schedule 16.02.2009


Ответы (4)


Назначение "" для buf[size+1] не сбрасывает размер buf, но это бессмысленно, потому что это дублирует небольшую часть того, что делает последующий memset (и это сбивает с толку ваш инструмент статического анализа - вы можете захотеть файл отчет об ошибке против него).

person dave-holm    schedule 17.02.2009

Помимо того факта, что char buf[size+1] не будет компилироваться, потому что size является значением времени выполнения, если предположить, что вы можете построить buf как массив размера 65, тогда memset(buf, 0, 65) не будет переполнением.

Скорее всего, ваш инструмент сбит с толку вашими синтаксическими проблемами.

[Изменить: больше информации]

Основываясь на комментариях к моему первоначальному сообщению, я предлагаю следующее:

#define size 64
char buf[size+1];
strcpy(buf, "");
memset(buf, 0, size+1);

Я считаю, что Роб Кеннеди прав; ваш инструмент использует значение инициализатора пустой строки в качестве размера массива, а не объявление статического массива.

person Randolpho    schedule 16.02.2009
comment
C99 имеет массивы с динамическим размером. - person Logan Capaldo; 16.02.2009
comment
Действительно? Ну цвет меня из игры. Очевидно, я не делал C слишком долго. - person Randolpho; 16.02.2009
comment
Причина, по которой он не скомпилируется, заключается в том, что вы не можете инициализировать массив с динамическим размером. Массивы динамического размера разрешены уже почти 10 лет. - person Rob Kennedy; 16.02.2009
comment
Тем не менее, инструмент может этого не осознавать. Он может использовать инициализатор для определения размера массива. - person Rob Kennedy; 16.02.2009
comment
Вызов strcpy избыточен; memset в любом случае просто перезапишет (пустую) строку. - person Matthew Crumley; 17.02.2009
comment
«… char buf[size+1] не будет компилироваться, потому что size является значением времени выполнения…» Поскольку size определен как целочисленная литеральная константа, size+1 является вполне допустимой константой времени компиляции, поэтому char buf[size+1 ] должен компилироваться; это происходит без предупреждения в GCC 4 с параметром -Wall -Wextra. Из спецификации C99 §6.6.1 и 6: - person Flash Sheridan; 01.04.2009
comment
Константное выражение может быть вычислено во время трансляции... может использоваться в любом месте, где может быть константа.... Целочисленное константное выражение* должно иметь целочисленный тип и должно иметь только операнды, которые являются целочисленными константами,... * Целочисленное константное выражение используется для указать... размер массива,... - person Flash Sheridan; 01.04.2009
comment
@Flash Шеридан: Ты прав. Однако, когда я написал свой ответ, размер был size_t, а не #define. Вопрос отредактирован. Проверьте историю. :) - person Randolpho; 01.04.2009

Это не переполнение буфера.

Это, вероятно, более чистый способ сделать это. Конечно, это занимает меньше строк кода.

#define size 64
char buf[size + 1] = {0};
person EvilTeach    schedule 17.02.2009

Это законно - буфер достаточно большой. Инструмент предупреждает вас, что size_t может быть больше, чем int, и попытка использовать его в качестве индексатора может привести к непредсказуемым результатам.

person sharptooth    schedule 16.02.2009
comment
Я не думаю, что это то, о чем предупреждает инструмент. В нем ясно сказано, что размер массива равен 1 и что используются индексы от 0 до 64. Он не жалуется на размеры целых чисел. - person Rob Kennedy; 16.02.2009
comment
измененный пример, чтобы избежать путаницы с size_t в будущем. - person An̲̳̳drew; 17.02.2009
comment
Ну, инструмент показывает паранойю по поводу размера массива, что неверно. Это может быть просто ошибка в инструменте - источник инструмента может сказать наверняка. Однако проблема с size_t хорошо известна, и в некоторых случаях она болезненно проявляется, особенно при переносе на 64-битные платформы. - person sharptooth; 17.02.2009