Я знаю, что можно переполнить обычный код:Переполнение над scanf ("% 8s", строка)?
char string [9];
scanf ("% s", string).
Но возможно ли переполнение scanf («% 8s», строка)? 8 является просто примером.
Я знаю, что «% 8s» работает как разграничить, но я также заметил, когда я строка ввода длиннее 8 символов, программа будет завершена из-за:
* стек Smashing обнаружен *: ./a .out прекращено
======= Backtrace: =========
...
Очевидно, есть флаг, который определяет стек Smashing возбуждает GCC по умолчанию , Так как это разбивка стека, то я предполагаю, что все еще возможно переполнение и выполнение произвольного кода.
В отличие от обычного переполнения, который управляет вызывающим устройством scanf («% s»), если scanf («% 8s») может переполняться, он будет переполняться в функции scanf, чтобы при попытке scanf получить контроль.
Но scanf - это системный вызов, который требует переключения режимов (переход из пользовательского режима в режим ядра), и внутренне он будет вызывать такие вещи, как чтение в stdin и т. Д. Поэтому не уверен, что мы можем переполняться в режиме ядра или что-то в этом роде. .
Комментарии приветствуются!
ОБНОВЛЕНИЕ >>
символ строки [9] предполагается, в приведенном выше примере. char string [8] в следующем действительном коде.
Вопрос действительно о кажущейся противоречивой истории между безопасным scanf («% 8s») и абортом GCC из-за разрыва стека.
упрощенный код:
void foo(pass some pointer) {
char input[8];
int input_number = 0;
while (1) { // looping console
printf some info;
scanf("%8s", input);
input_number = atoi(input);
if ((strlen(input) == 1) && (strncmp(input, "q", 1) == 0)) {
input_number = -1;
}
switch (input_number) {
case -1: to quit the console if input = 'q';
default: to print info that pointer refers to;
...
}
}
}
Примечание:
- Foo называется кем-то другим.
- Хотя строка содержит 8 байтов в реальном код с "% 8s", я не думаю, что это привести к разгрому.
scanf - это функция библиотеки времени выполнения - нет режима переключения, поскольку он работает в пользовательском пространстве, если только он не должен запрашивать заполнение буфера, и в этом случае он будет вызывать чтение или чтение. – wallyk
, как указано несколько раз в ответах, добавлен нулевой байт, поэтому вам понадобится буфер с 9 символами, чтобы принять до 8 символов ввода. – ysth
Как много людей указали, ваше предположение в «Примечание 2.» неправильно. Этот пример позволяет использовать один байт переполнения, что и обнаруживает gcc. – caf