2

The following code contains an 8 bytes buffer.

void vuln() { char buffer[8]; gets(buffer); printf("%s",buffer); } int main() { vuln(); return 0; } 

So, only 8 bytes of stack is expected to be reserved for this buffer. But the disassembly shows 16 bytes being reserved.

(gdb) Dump of assembler code for function vuln: 0x000000000040057d <+0>: push %rbp 0x000000000040057e <+1>: mov %rsp,%rbp 0x0000000000400581 <+4>: sub $0x10,%rsp 0x0000000000400585 <+8>: lea -0x10(%rbp),%rax 0x0000000000400589 <+12>: mov %rax,%rdi 0x000000000040058c <+15>: callq 0x400480 <gets@plt> 0x0000000000400591 <+20>: lea -0x10(%rbp),%rax 0x0000000000400595 <+24>: mov %rax,%rsi 0x0000000000400598 <+27>: mov $0x400644,%edi 0x000000000040059d <+32>: mov $0x0,%eax 0x00000000004005a2 <+37>: callq 0x400450 <printf@plt> 0x00000000004005a7 <+42>: leaveq 0x00000000004005a8 <+43>: retq End of assembler dump. 

Some actions are to be perform based on the expected size of the buffer on the stack in an automated script. But this crippled the script. May I know the reason why 16 bytes were allocated for the buffer so that I can incorporate it in the script ?

2
  • I've compiled it with GNU C -O0 and also got 16 bytes allocated in memory; with -O6 it grew to 32 bytes. See my answer below. Commented Jul 10, 2014 at 13:07
  • can you add which are these actions "to be performed based on the expected size of the buffer on the stack"? Perhaps there's an answer to the whole problem. Commented Jul 10, 2014 at 13:10

3 Answers 3

2

The x86-64 ELF psABI requires the stack pointer to be aligned: section 3.2.2 ("The Stack Frame") says

... The end of the input argument area shall be aligned on a 16 byte boundary. In other words, the value (%rsp− 8) is always a multiple of 16 when control is transferred to the function entry point. The stack pointer, %rsp, always points to the end of the latest allocated stack frame.

Your function allocates 8 bytes on the stack and then calls a one-argument function, gets; that function's one argument is passed in registers, so to maintain the ABI requirement, the compiler has to move the stack pointer down an additional 8 bytes before it makes the function call.

Sign up to request clarification or add additional context in comments.

2 Comments

So, in (%rsp - 8), what is the value 8 depending on ? When I used a 45 bytes buffer, the compiler assigned 48 bytes in the stack. I am not able to find the math in it. If I was to go by my original calculation, 48 bytes is perfect because memory is allocated in words (4 bytes) and 48 is 12 words. But what about the ABI requirement in this case ?
In that example, on entry to the function, the stack pointer has the value (k*16 - 8) for some unknown k. After push %rbp, its value is (k-1)*16; after sub $0x30,%rsp, its value is (k-4)*16; and then call gets@plt implicitly does push %rip, making the stack pointer (k-4)*16 - 8 on entry to gets. Does that help you understand how it works?
1

As @Zack put in his answer, x86-64 ABI requires 16 bytes stack alignment. If you are using gcc on x86 or x86_64 by default stack is 16 bytes aligned.

From gcc documentation:

-mpreferred-stack-boundary=num Attempt to keep the stack boundary aligned to a 2 raised to num byte boundary. If -mpreferred-stack-boundary is not specified, the default is 4 (16 bytes or 128 bits).

https://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html

See the documentation further, if SSE is disabled gcc may align stack to 8 bytes (and thus violate ABI requirements).

Comments

0

You can't control what the compiler will do on the stack. You also can't control the order of variables on the stack. The compiler is also allowed to introduce padding so to better align things in memory (although not inside arrays: this is strictly forbidden). In certain cases it won't even allocate variables on stack, but in registers instead.

If you has specific needs on assembly level, do it in assembly.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.