Объясните, что именно происходит в этом фрагменте кода на С?

Встретил в книге по другому языку пример такого кода на C
int main(int argc, char **argv) {
    unsigned long a[1];
    a[3] = 0x7ffff7b36cebUL;
    return 0;
}

Объясняется он следующим образом:

В сгенерированном компилятором C машинном коде функции main массив a размещен в стеке на три слова раньше адреса возврата, поэтому запись значения 0x7ffff7b36cebUL в a[3] изменяет адрес возврата из main, так что он указывает на какой-то код из стандартной библиотеки C, который пытается прочитать пароль из файла .netrc. После возврата из main выполнение возобновляется не с команды, следующей за вызовом main, а с машинного кода, соответствующего таким строкам из библиотеки:
warnx(_("Error: .netrc file is readable by others."));
warnx(_("Remove password or make file unreadable by others."));
goto bad;


Мне как человеку, не знакомому с языками семейства С, это объяснение никак не проясняет ситуацию. Расскажите, пожалуйста, подробнее и более простым языком, как такой код приводит к возникновению ошибки. Особенно вот это
запись значения 0x7ffff7b36cebUL в a[3] изменяет адрес возврата из main
  • Вопрос задан
  • 212 просмотров
Решения вопроса 1
wataru
@wataru Куратор тега C++
Разработчик на С++, экс-олимпиадник.
unsigned long a[1];

Заводит локальную переменную - массив длины 1.

a[3] = 0x7ffff7b36cebUL;

Записывает какие-то данные в четвертую ячейку массива a. Но выделен то он только длины 1. Эта запись идет в какую-то память, где что-то нужное системе уже лежит.

Дальше надо понять, а как вообще работают функции в современных архитектурах. У процессора есть стек. Эта область памяти, которая как стопка бумаг - можно класть в нее новые данные сверху и забирать их сверху-же. При вызове функции в стек кладется адрес кода, куда надо вернутся после выполнения функции. Процессор при выходе из функции берет адрес из стека и продолжает исполнение программы оттуда. Именно так можно вызывать одну и ту же функцию (один и тот же код!) из разных мест в программе и потом вернутся в эти самые разные места. Также в стек кладутся параметры функции и на стеке же создаются локальные переменные.

Вот и получается, что локальный массив a и адрес возврата лежат в этом самом стеке где-то рядом. Ну и так получается, что за массивом a, через пару ячеек, лежит адрес возврата.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы