Исправление переполнения стека в переполнении стека

Я прочитал приведенный ниже код в книге, в которой говорилось, что это уязвимо для переполнения стека. Хотя fgets () был использован, я не смог понять, почему он уязвим?

Насколько я понимаю, использование fgets () вместо gets () обычно помогает нам избавиться от переполнения буфера, поместив нулевое значение в конце. Я что-то пропустил? Что следует использовать вместо fgets () для исправления переполнения стека?

void getinp(char *inp, int siz)
{
puts("Input value: ");
fgets(inp, siz, stdin);
printf("buffer3 getinp read %s\n", inp);
}

void display(char * val)
{
char tmp[16];
sprintf(tmp, "read val: %s\n", val);
puts(tmp);
}

int main(int argc, char *argv[])
{
char buf[16];
getinp(buf, sizeof(buf));
display(buf);
printf("buffer3 done\n");
}

0

Решение

В display tmp объявлен как 16 charдолго, но вы пишете (с sprintf) там не только val (который гарантированно будет 16 символов или меньше), но также "read val: " и финал \n).

Это означает, что если пользователь вставляет более 16-11 = 5 символов, у вас переполнение буфера в display,

Одним из решений может быть объявление buf в display быть достаточно большим, чтобы хранить оба val и дополнительный текст, хотя в реальном мире вы бы просто написать stdout с помощью printf (без промежуточного буфера).

Кроме того, обычно, когда у вас есть sprintf и есть некоторый потенциальный риск переполнения буфера, который вы используете snprintf вместо этого (на самом деле, я использую это всегда); snprintfвместо переполнения буфера обрезает вывод, если он будет слишком длинным, и возвращает количество символов, которое было бы записано, если бы выходной буфер был достаточно большим.

1

Другие решения

На дисплее нет никакого способа убедиться, что val + 12 байтов помещается в 16-символьный буфер.

0

По вопросам рекламы [email protected]