Question

When running the following intentional stack smashing code, strcat copies the value of source exactly ten times.

#include <stdio.h>
#include <stdlib.h>

int main() {
    char a[16];
    char b[16];
    char c[32];

    strcpy(a, "abcdefghijklmnop");
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    strcpy(b, "ABCDEFGHIJKLMNOP");
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    strcpy(c, b);
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    strcat(c, b);
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    return 0;
}

Output:

a = abcdefghijklmnop b = c =

a = abcdefghijklmnopABCDEFGHIJKLMNOP b = ABCDEFGHIJKLMNOP c =

a = abcdefghijklmnopABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP b = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP c = ABCDEFGHIJKLMNOP

a = abcdefghijklmnopABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP b = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP c = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP

** stack smashing detected *: ./strcpytest terminated

Building parameters:

gcc -O0 -g3 -Wall -c -fmessage-length=0

The code is run on a x86_64 architecture.

Why does it only concatenate ten times?

Was it helpful?

Solution

The behaviour of strcpy() and strcat() is undefined for overlapping strings. Both of your writes to c[] are therefore suspect, and rather than just testing smashing the stack, you're also testing your compiler's treatment of this undefined behaviour.

I'd expect the strcpy(c, b) line to fail, but the implementation must somehow get b's length before it overwrites the trailing zero at the start of c. This could happen if it copies from the last byte to the first, for example.

strcat(c, b) may be implemented in a more straightforward manner. Maybe ten times the data is enough to hit some limit that terminates it.

If you want to just test corrupting the stack, don't use these methods. Instead just use one array, and write past the end of it with a loop, e.g. "for (i = 0; i < 1000000; i++) c[i] = 'h';"

OTHER TIPS

If your platform uses memory-protection and has its stack growing down, like x86 (What is the direction of stack growth in most modern systems?), picking any stack position and writing to increasing addresses from there (like for a string...) means you don't go in the direction of stack-expansion but origin of stack, eventually running over it and plunging to your death on an intentially non-mapped guard-page, in which case you get the nice error-message you mentioned.

The error message can and is personalised this way to give you a hint what happened.

Aside: Changing anything at all might change the behavior of your code, as the platform is not obligated to behave that way.
2nd aside: The astounding thing is that strcpy(c, b); behaves as if it did not overwrite the terminator of the string beginning in b and terminated in c.

I am getting output like this, using gcc compiler:

a = abcdefghijklmnop
b = 
c = 

a = abcdefghijklmnopABCDEFGHIJKLMNOP
b = ABCDEFGHIJKLMNOP
c = 

a = abcdefghijklmnopABCDEFGHIJKLMNOP
b = ABCDEFGHIJKLMNOP
c = ABCDEFGHIJKLMNOP

a = 
b = ABCDEFGHIJKLMNOP
c = ABCDEFGHIJKLMNOPABCDEFGHIJKLMNOP

It is because You are not providing required size for terminator. Just try it:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char a[17];
    char b[17];
    char c[33];

    strcpy(a, "abcdefghijklmnop");
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    strcpy(b, "ABCDEFGHIJKLMNOP");
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    strcpy(c, b);
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    strcat(c, b);
    printf("a = %s\nb = %s\nc = %s\n\n", a, b, c);

    return 0;
}

Every thing is fine now. Thanks Baldrick.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top