Привет, друзья!
Наткнулся на интересный пример в сети, решил, что будет хорошо его добавить сюда.
Имеется код:
C++ (Qt)
#include <iostream>
int foo(){
std::cout << "Hi! You are out of range :^)";
return 1;
}
void bar(){
int arr[500];
arr[501] = reinterpret_cast<int> (&foo);
}
int main(){
bar();
return 0;
}
Видно, что в функции bar мы производим запись в ячейку с номером на 2 больше максимально допустимого.
Данный код я скомпилировал используя компилятор MinGW 4.92. Далее приводится результат работы (аттач 1).
Видно, что в коде происходит присвоение элементу массива
arr с номером
501 адреса функции
foo(). Никакого вызова функции
foo() в коде нет. Однако, при исполнении программы, происходит вызов функции
foo(), о чем свидетельствует появление в консоли строчки
"Hi! You are out of range :^)".
Почему это происходит? Если мы посмотрим на устройство стека данной программы (аттач 2), то несложно заметить, что при попытке обращения к ячейке a[501] мы обращаемся в ячейку, которая отвечает за адрес возврата в место вызова функции bar. Переписав это значение адресом функции foo возврат состоится именно в неё! Важно отметить, что на разных системах с разными компиляторами стек может быть устроен по разному, соответственно, для воспроизведения данного примера может потребоваться заменить 501 на другое число чуть больше 499.