Reveal the solution.
Using the debugger you probably noticed that the words array contains the
same word multiple times, or complete garbage (depending on where you placed
your break point). If you looked even more closely, you may noticed that it
contains the same pointer pointing to the same address multiple times.
The root cause is the input function. Letโs see why. Here is a stripped down
version of the exercise program, focusing on the problem. Click on the buttons
below to simulate this programโs stack line by line.
#include <stdio.h>
#include <stdlib.h>
char* input(void) {
char word[4] = {0, 0, 0, 0}; // 4 bytes, stack allocated.
fgets(word, 4, stdin);
return word; // Return an address to the stack!
}
int main(void) {
int i = 0; // 4 bytes, stack allocated.
char* words[2] = {NULL, NULL}; // 8 bytes, stack allocated (assuming 32-bits pointers).
for (i = 0; i < 2; i++) {
words[i] = input();
printf("words[%d] == %s\n", i, words[i]);
}
return 0;
}
Previous
Next
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 ????????
โ ffffdff4 ????????
โ ffffdff0 ????????
โ ffffdfec ????????
โ ffffdfe8 ????????
โ ffffdfe4 ??
โ ffffdfe3 ??
โ ffffdfe2 ??
โ ffffdfd1 ??
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 ????????
โ ffffdff0 ????????
โ ffffdfec ????????
โ ffffdfe8 ????????
โ ffffdfe4 ??
โ ffffdfe3 ??
โ ffffdfe2 ??
โ ffffdfd1 ??
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 00000000 words[0]
โ ffffdfec ????????
โ ffffdfe8 ????????
โ ffffdfe4 ??
โ ffffdfe3 ??
โ ffffdfe2 ??
โ ffffdfd1 ??
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 00000000 words[0]
โ ffffdfec ????????
โ ffffdfe8 ????????
โ ffffdfe4 ??
โ ffffdfe3 ??
โ ffffdfe2 ??
โ ffffdfd1 ??
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 00000000 words[0]
โ ffffdfec ???????? <input's return address>
โ ffffdfe8 ???????? <input's stored ebp>
โ ffffdfe4 ??
โ ffffdfe3 ??
โ ffffdfe2 ??
โ ffffdfd1 ??
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 00000000 words[0]
โ ffffdfec ???????? <input's return address>
โ ffffdfe8 ???????? <input's stored ebp>
โ ffffdfe4 00 '\0' word[3]
โ ffffdfe3 00 '\0' word[2]
โ ffffdfe2 00 '\0' word[1]
โ ffffdfd1 00 '\0' word[0]
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 00000000 words[0]
โ ffffdfec ???????? <input's return address>
โ ffffdfe8 ???????? <input's stored ebp>
โ ffffdfe4 00 '\0' word[3]
โ ffffdfe3 43 'C' word[2]
โ ffffdfe2 42 'B' word[1]
โ ffffdfd1 41 'A' word[0]
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 00000000 words[0]
โ ffffdfec ???????? <input's return address>
โ ffffdfe8 ???????? <input's stored ebp>
โ ffffdfe4 00 '\0' word[3]
โ ffffdfe3 43 'C' word[2]
โ ffffdfe2 42 'B' word[1]
โ ffffdfd1 41 'A' word[0]
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโ
โ ffffdfec ???????? <input's return address> โ
โ ffffdfe8 ???????? <input's stored ebp> โ
โ ffffdfe4 00 '\0' word[3] โ
โ ffffdfe3 43 'C' word[2] โ
โ ffffdfe2 42 'B' word[1] โ
โ ffffdfd1 41 'A' word[0] ๐ญฎโโโโโโโโโโโโโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000000 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโโ
โ ffffdfec ???????? <printf's return address> โ
โ ffffdfe8 ???????? <printf's stored ebp> โ
โ ffffdfe4 ?? <printf's variables> โ
โ ffffdfe3 ?? <printf's variables> โ
โ ffffdfe2 ?? <printf's variables> โ
โ ffffdfd1 ?? <printf's variables> ๐ญฎโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000001 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโโ
โ ffffdfec ???????? <printf's return address> โ
โ ffffdfe8 ???????? <printf's stored ebp> โ
โ ffffdfe4 ?? <printf's variables> โ
โ ffffdfe3 ?? <printf's variables> โ
โ ffffdfe2 ?? <printf's variables> โ
โ ffffdfd1 ?? <printf's variables> ๐ญฎโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000001 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโ
โ ffffdfec ???????? <input's return address> โ
โ ffffdfe8 ???????? <input's stored ebp> โ
โ ffffdfe4 ?? <printf's variables> โ
โ ffffdfe3 ?? <printf's variables> โ
โ ffffdfe2 ?? <printf's variables> โ
โ ffffdfd1 ?? <printf's variables> ๐ญฎโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000001 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโ
โ ffffdfec ???????? <input's return address> โ
โ ffffdfe8 ???????? <input's stored ebp> โ
โ ffffdfe4 00 '\0' word[3] โ
โ ffffdfe3 00 '\0' word[2] โ
โ ffffdfe2 00 '\0' word[1] โ
โ ffffdfd1 00 '\0' word[0] ๐ญฎโโโโโโโโโโโโโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000001 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโ
โ ffffdfec ???????? <input's return address> โ
โ ffffdfe8 ???????? <input's stored ebp> โ
โ ffffdfe4 00 '\0' word[3] โ
โ ffffdfe3 46 'F' word[2] โ
โ ffffdfe2 45 'E' word[1] โ
โ ffffdfd1 44 'D' word[0] ๐ญฎโโโโโโโโโโโโโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000001 i
โ ffffdff4 00000000 words[1]
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโ
โ ffffdfec ???????? <input's return address> โ
โ ffffdfe8 ???????? <input's stored ebp> โ
โ ffffdfe4 00 '\0' word[3] โ
โ ffffdfe3 46 'F' word[2] โ
โ ffffdfe2 45 'E' word[1] โ
โ ffffdfd1 44 'D' word[0] ๐ญฎโโโโโโโโโโโโโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000001 i
โ ffffdff4 ffffdfd1 words[1] โโโโโโโโโโโโโโโโโ
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโค
โ ffffdfec ???????? <input's return address> โ
โ ffffdfe8 ???????? <input's stored ebp> โ
โ ffffdfe4 00 '\0' word[3] โ
โ ffffdfe3 46 'F' word[2] โ
โ ffffdfe2 45 'E' word[1] โ
โ ffffdfd1 44 'D' word[0] ๐ญฎโโโโโโโโโโโโโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000001 i
โ ffffdff4 ffffdfd1 words[1] โโโโโโโโโโโโโโโโโโ
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโโค
โ ffffdfec ???????? <printf's return address> โ
โ ffffdfe8 ???????? <printf's stored ebp> โ
โ ffffdfe4 ?? <printf's variables> โ
โ ffffdfe3 ?? <printf's variables> โ
โ ffffdfe2 ?? <printf's variables> โ
โ ffffdfd1 ?? <printf's variables> ๐ญฎโโโโโ
๐ญฏ Address Data
โ ffffe000 ???????? <main's return address>
โ ffffdffc ???????? <main's stored ebp>
โ ffffdff8 00000002 i
โ ffffdff4 ffffdfd1 words[1] โโโโโโโโโโโโโโโโโโ
โ ffffdff0 ffffdfd1 words[0] โโโโโโโโโโโโโโโโโโค
โ ffffdfec ???????? <printf's return address> โ
โ ffffdfe8 ???????? <printf's stored ebp> โ
โ ffffdfe4 ?? <printf's variables> โ
โ ffffdfe3 ?? <printf's variables> โ
โ ffffdfe2 ?? <printf's variables> โ
โ ffffdfd1 ?? <printf's variables> ๐ญฎโโโโโ
As we can see above, inputโs issue is that it returns data from its stack,
data which gets overwritten right away when another function is called. So,
what do you think the fix would be?
Tip
Click here to get a first hint.
Donโt use the stack, use the heap. How would you allocate memory on the heap?
Click here to get a second hint.
malloc. malloc is the solution. Donโt forget its friend, free.