Это зависит от целевой платформы, флагов компилятора и компиляции.
Например, G CC 7.2 x86 в режиме отладки (-O0
) выравнивает кадры стека на 16-байтовой границе и выделяет указатель кадра (ebp).
Пример: ( ссылка Godbolt )
bof(char*):
push ebp ; -4
mov ebp, esp
sub esp, 40 ; -40
sub esp, 8 ; -8
push DWORD PTR [ebp+8] ; -4
lea eax, [ebp-32] ; 32 bytes to top of stack frame
push eax ; -4
call strcpy ; stack is aligned to 16 bytes (-64)
add esp, 16
mov eax, 1
leave
ret
При оптимизации (-O2
) указатель кадра опускается, но стек выровнен по 16 байтам ( ссылка Годболт ):
bof(char*):
sub esp, 52 ; -52
push DWORD PTR [esp+56] ; -4
lea eax, [esp+20] ; 36 bytes to top of stack frame
push eax ; -4
call strcpy ; stack is aligned to 16 bytes (-64)
mov eax, 1
add esp, 60
ret
с принудительным выравниванием стека 4 байта (-O2 -mpreferred-stack-boundary=2
) ( ссылка Годболт ):
bof(char*):
sub esp, 24 ; -24
push DWORD PTR [esp+28] ; -4
lea eax, [esp+4] ; 24 bytes to top of stack frame
push eax ; -4
call strcpy
mov eax, 1
add esp, 32
ret
С включенной защитой стека (-O2 -fstack-protector-all
) ( godbolt link ):
bof(char*):
sub esp, 52 ; -52
mov eax, DWORD PTR gs:20
mov DWORD PTR [esp+36], eax ; stack check value at -16 (-52+36)
xor eax, eax
push DWORD PTR [esp+56] ; -4
lea eax, [esp+16] ; 40 bytes to top of stack frame, leaving exactly 24 bytes to check value
push eax
call strcpy
add esp, 16
mov edx, DWORD PTR [esp+28]
xor edx, DWORD PTR gs:20
jne .L5
mov eax, 1
add esp, 44
ret
.L5:
call __stack_chk_fail
Другие компиляторы могут иметь совершенно разные результаты.
В реальной жизни переполнение буфера используется в режиме сборки путем анализа инструкций и подсчета байтов до адреса возврата функции, поэтому не имеет значения, каким был исходный код или как он был скомпилирован (эта информация часто в любом случае недоступна) .