try this:
#include <stdio.h>
#include <string.h>
int main(void) {
char buffer[80];
fgets(buffer, sizeof(buffer), stdin);
printf("echo %s\n", buffer);
return 0;
}
In C you need to manage memory. In the example above we allocate a buffer of 80 bytes on the stack; asked the standard library to read up to 80 characters and then generated the output.
In your code snippet, you had an uninitialised pointer and then you where giving the address of that pointer (which is a stack address) to scanf. scanf will then proceed to read into your stack... which means that it will typically overwrite the return address of your function.
try this snippet:
int main(void) {
char *buffer;
printf("%p\n", &buffer); // This prints a stack address
}
I was looking for some reference that would explain the concept of clobbering the stack by writing into it. This was the top link I could find.
https://en.wikibooks.org/wiki/X86_Disassembly/Calling_Conventions
When C calls a function, it will do the following:
- push arguments into the stack
- call the function which results in stack pointer and return address being pushed into the stack
- push into the stack space for local variables (e.g. our char *word;) in your initial example.
On x86 stack grows up (i.e. to lower addresses) so when you write into the memory region of a local variable and you didn't reserve space for what you want to write you are effectively overwriting the call stack.
It helps to have an idea of how a to program a CPU with assembly, specially stack and function call / return in order to properly understand C. It is also extremely useful even when one is using higher order languages; sooner or later one needs to understand what is going on under all those layers of abstraction.