简体   繁体   中英

How come this string doesn't overflow the buffer?

I ran this code on a mac and also on linux:

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

int main (int argc, char *argv[]){

    int value = 5;
    char buffer_one[8], buffer_two[8];

    strcpy(buffer_one, "one");
    strcpy(buffer_two, "two");

    printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
    printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
    printf("[BEFORE] value is at %p and is %i (0x%08x)\n", &value, value, value);

    printf("\n[STRCPY] copying %i bytes into buffer two\n\n", strlen(argv[1]));
    strcpy(buffer_two, argv[1]); 

    printf("[AFTER] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
    printf("[AFTER] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
    printf("[AFTER] value is at %p and is %i (0x%08x)\n", &value, value, value);
}

On the mac, if i entered "1234567890" as a command line argument, the 90 overflowed into buffer one as I would expect because the buffer of 8 bytes was exceeded by 2.

However if I run it on my Linux system, it takes many more characters to overflow the buffer. How come/why can I get away with exeeding the buffer in Linux?

Also as A side note, on both systems, the entire string will still be printed in buffer two and only the overflowed items in buffer one. Why would that happen? How come the rest of the characters wouldn't just go to the next? If that question wasn't phrased well, heres an example:

If I enter 1234567890 on my mac, the 1234567890 will be printed in buffer two and the 90 would be printed in buffer one. How can the 90 still fit inside buffer two even though it has overflowed. (it is the same concept on linux but it takes more than 10 bytes to overflow)

The answer to your first question is that the alignment of variables in memory is implementation-defined. (See Section 6.2.8 "Alignment of objects" in the C11 draft .) Basically, different compilers may require a different minimum number of bytes to be between two objects in memory. The compiler you used on the Mac packed the two 8-byte buffers right next to each other on the stack, likely because the alignment of char[] is 8 or less bytes. The compiler you used on Linux left more bytes between the two addresses, probably because the alignment of char[] is 16 bytes.

For your second question, buffer_one and buffer_two are just two addresses in a contiguous chunk of memory that your program has access to. In this case, due to the implementation of the stack, buffer_two appears at a lower address than buffer_one in memory, so data written to buffer_two overflows to buffer_one . The reason you print "1234567890" from buffer_two and "90" from buffer_one is that printf() starts reading bytes at the address you give it until it reads a null-terminator ( 0x00 ).

So, when you strcpy() "1234567890" to buffer_two , you actually write 11 bytes, including the null-terminator ( 0x00 ) at the end of the string. On your Mac, buffer_two and buffer_one were 8 bytes apart, so when printf() reads from buffer_two , it reads 10 characters before seeing the null-terminator, which happens to be after the address pointed to by buffer_one . When printf() reads from buffer_one , it reads 2 characters before seeing the null-terminator.

The way it can be "inside" is because there isn't really a stop at the end of "inside". You ask for a char[] of length 8 and you get it, presumably the second is right next to it (though the compiler is free to rearrange such things if it wants). You then write, say, 10 chars into the first buffer. When you print that buffer it has no idea that it's supposed to only have 8 characters in it, it knows where it starts and goes until it gets to a NUL character.

So it will go and print the whole string. The other buffer that was right beside it also knows where its memory starts, which happens to be where the 9 from the string overflowed into its space. Printing that one tells it to go to the first memory location for its string and print until it gets to a NUL , which is 90 in this case.

So you are overflowing, just not in a particularly destructive or dangerous way for this example. If you wrote a lot more data into the string you could start overwriting not just the adjacent string buffer but other potentially important things on the stack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM