The SIGSEGV that has never occurred!

Some days ago, I found out with an easy problem: make a program that generates a Segmentation Fault! The easiest way I thought was generate a simple buffer overflow and write on a place that it’s not mine!

The thing interesting on this post was that the program I made HAS NEVER FINISHED! and it’s really simple… Let you the code:

int main(void)
{
int i = 0;
int array[1];

while (i < 100)
{
array[i++] = 1;
printf(”%i\n”, i);
}

return 0;
}

So… Did you find out the error?

Here you got the results generated by the program

mesarpe@cesar:~/Programacion$ ./sigsegv
2
2
2
2
2
2
2
2
2

It has been compiled with gcc for 32 bits:

mesarpe@cesar:~/Programacion$ gcc -m32 -g -o sigsegv sigsegv.c

Maybe you have some skills and you find out the problem, and maybe you don’t… This program has surprised me, so… I’m gonna explain what has happened!

On ANSI-C we don’t have an specified order for the variables so the compiler has the freedom to decide where to put them on our stack. What my compiler has done was:

Here you can see where the array is saved and where the i integer

Here you can see where the array is saved and where the i integer

Well… You want to know directly from gdb the address and results:

Leyendo símbolos desde /home/mesarpe/Programacion/hack/sigsegv…done.
(gdb) b main
Interruption Point 1 at 0×80483ed: file sigsegv.c, line 16.
(gdb) r
Starting program: /home/mesarpe/Programacion/hack/sigsegv

Breakpoint 1, main () at sigsegv.c:16
16        int i = 0;
(gdb) n
20        while (i < 100)
(gdb) n
22            array[i++] = 1;
(gdb) p &array[0]
$1 = (int *) 0xbffff454
(gdb) p &array[1]
$2 = (int *) 0xbffff458
(gdb) p &array[2]
$3 = (int *) 0xbffff45c
(gdb) p &i
$4 = (int *) 0xbffff45c
(gdb) n
23            printf(”%i\n”, i);
(gdb) n
1
20        while (i < 100)
(gdb) n
22            array[i++] = 1;
(gdb) n
23            printf(”%i\n”, i);
(gdb) n
2
20        while (i < 100)
(gdb) n
22            array[i++] = 1;
(gdb) n
23            printf(”%i\n”, i);
(gdb) print i
$5 = 2
(gdb) n
2
20        while (i < 100)
(gdb) n
22            array[i++] = 1;
(gdb) p i
$6 = 2
(gdb) n
23            printf(”%i\n”, i);
(gdb) p i

What has happened is the next, when we set the array[2] value on 1, we write on the integer i value (that) is 2 and is changed to 1). So when we increment the i value, we are setting a 2 again. Curious, isn’t?

Anyway, this little code must inspire you to AVOID the Buffer Overflows, even when they are complicated!

One Response to “The SIGSEGV that has never occurred!”

  1. Pablo says:

    Interesting, I had to change the assignment to make it work because my compiler uses array[1] instead of array[2] for i.

    Here’s an easy way to force a segfault:

    int *p = 0;
    *p = 0xDEADBEEF;

Leave a Reply