Я упомянул «переполнение буфера» в комментарии к ответу Пифагра, наверное, мне следует уточнить, что я имел в виду. В C недостаточно знать, что работать непосредственно с памятью опасно - вы также должны понимать, как это опасно. Мне не очень нравится метафора «стреляй себе в ногу» во всех этих случаях - большую часть времени это не то, что ты нажимаешь на спусковой крючок, но часто это актер, интересы которого противоречат твоим и / или твоим пользователям ». ,
Например, в архитектуре с нисходящим стеком (большинство популярных архитектур соответствуют этому требованию - как правило, x86 и ARM включены), когда вы вызываете функцию, адрес возврата для функции будет помещен в стек после локальных переменных, определенных в Тело функции. Поэтому, если вы объявите буфер как локальную переменную и откроете эту переменную для внешнего мира, не проверяя переполнение буфера, вот так:
void myFn(void) {
char buf[256];
gets(buf);
}
внешний пользователь может отправить вам строку, которая перезаписывает адрес возврата из стека - в основном, он может изменить представление вашей программы во время выполнения графа вызовов, который приводит к текущей функции. Таким образом, пользователь дает вам строку, которая является двоичным представлением некоторого исполняемого кода для вашей архитектуры, достаточного заполнения для переполнения стека myFn
и некоторых дополнительных данных, чтобы перезаписать адрес возврата, myFn
чтобы он указывал на код, который он дал вам. Если это происходит, то, когда myFn
обычно возвращал бы управление своему вызывающему, он вместо этого переходил к коду, предоставленному злоумышленником. Если вы пишете код на C (или C ++), который потенциально может быть подвержен ненадежным пользователям, вам необходимо понять этот вектор атаки, Вы должны понимать, почему переполнение буфера в стеке часто (но не всегда) легче использовать, чем в куче, и вы должны понимать, как распределяется память в куче (не слишком подробно, обязательно, но Идея о том, что у malloc()
'ed области есть управляющие структуры, окружающие ее, может помочь понять, почему ваша программа падает в другой malloc()
или в free()
).
C предоставляет вам низкоуровневую информацию о том, как работает ваша машина, и дает вам более прямой контроль над вашей машиной, чем любой другой язык, отредактированный пользователем, который широко используется сегодня. С большой силой приходит большая ответственность - вам действительно нужно понимать эти детали низкого уровня, чтобы работать с C безопасно и эффективно.