scanf не должен превышать переполнение буфера - PullRequest
2 голосов
/ 12 ноября 2009

У меня есть буфер, и я не хочу, чтобы пользователь вводил больше символов, чем может вместить буфер (чтобы избежать переполнения буфера).

Я использую scanf и сделал так:

char buffer[30] = {'\0'};
scanf("%30s", buffer);

Тем не менее, я знаю, что я защищен, если пользователь вводит больше 30. Однако, если пользователь вводит больше 30, будет ли буфер нулевым?

Ответы [ 3 ]

2 голосов
/ 12 ноября 2009

Из руководства scanf:

s Соответствует последовательности непробельные символы; следующий указатель должен быть указатель на символ, и массив должен быть достаточно большим, чтобы принять всю последовательность и завершающий символ NUL. строка ввода останавливается на пустом месте или на максимальной ширине поля, что наступит раньше.

Вы вызываете UB. Попробуйте:

#define str(x) #x
#define xstr(s) str(x)
#define BUFSIZE 30

char buffer[ BUFSIZE + 1 ];
scanf("%" xstr(BUFSIZE) "s", buf);

Чтобы игнорировать что-либо, кроме BUFSIZE, символы подавляют присваивание:

scanf("%" xstr(BUFSIZE) "s%*", buf);

Вам также следует проверить, ввел ли пользователь возврат / перевод строки, и прекратить действие scanf, если у него есть:

scanf("%" xstr(BUFSIZE) "[^\n]s%[^\n]*", buf);

и рекомендуется проверять возвращаемые значения, поэтому:

int rc = scanf("%" xstr(BUFSIZE) "[^\n]s%[^\n]*", buf);

и, наконец, проверьте, осталось ли что-нибудь (например, перевод строки, и используйте его):

if (!feof(stdin))
    getchar();
2 голосов
/ 12 ноября 2009

scanf() со спецификатором преобразования "% s" добавляет в буфер завершающий нулевой символ.

Но , вы запрашиваете 30 символов, что на самом деле означает 31 и имеет место только для 30. Вы должны использовать максимальную ширину поля 29.

char buffer[30] = {'\0'};
scanf("%29s", buffer);

Также обратите внимание, что спецификатор преобразования "%c" работает почти так же, как "%s", но не добавляет завершающий нулевой символ и не сбрасывает пробел из ввода. В зависимости от того, что вы ожидаете, это может быть лучше, чем использование "% s".

char buffer[30] = {'\0'};
scanf("%29c", buffer);
buffer[29] = '\0';
1 голос
/ 12 ноября 2009

У вас будет переполнение буфера, потому что вы не разрешили завершающий символ NUL. Объявите свой буфер следующим образом:

char buffer[31];

и с тобой все будет в порядке.

...