Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this intentionally incorrect use of strcpy not fail horribly?

Tags:

c

malloc

strcpy

Why does the below C code using strcpy work just fine for me? I tried to make it fail in two ways:

1) I tried strcpy from a string literal into allocated memory that was too small to contain it. It copied the whole thing and didn't complain.

2) I tried strcpy from an array that was not NUL-terminated. The strcpy and the printf worked just fine. I had thought that strcpy copied chars until a NUL was found, but none was present and it still stopped.

Why don't these fail? Am I just getting "lucky" in some way, or am I misunderstanding how this function works? Is it specific to my platform (OS X Lion), or do most modern platforms work this way?

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

int main() {
    char *src1 = "123456789";
    char *dst1 = (char *)malloc( 5 );

    char src2[5] = {'h','e','l','l','o'};
    char *dst2 = (char *)malloc( 6 );

    printf("src1: %s\n", src1);
    strcpy(dst1, src1);
    printf("dst1: %s\n", dst1);
    strcpy(dst2, src2);
    printf("src2: %s\n", src2);
    dst2[5] = '\0';
    printf("dst2: %s\n", dst2);

    return 0;
}

The output from running this code is:

$ ./a.out   
src1: 123456789
dst1: 123456789
src2: hello 
dst2: hello
like image 413
Gabe Durazo Avatar asked Aug 21 '11 17:08

Gabe Durazo


1 Answers

First, copying into an array that is too small:

C has no protection for going past array bounds, so if there is nothing sensitive at dst1[5..9], then you get lucky, and the copy goes into memory that you don't rightfully own, but it doesn't crash either. However, that memory is not safe, because it has not been allocated to your variable. Another variable may well have that memory allocated to it, and later overwrite the data you put in there, corrupting your string later on.

Secondly, copying from an array that is not null-terminated:

Even though we're usually taught that memory is full of arbitrary data, huge chunks of it are zero'd out. Even though you didn't put a null-terminator in src2, chances are good that src[5] happens to be \0 anyway. This makes the copy succeed. Note that this is NOT guaranteed, and could fail on any run, on any platform, at anytime. But you got lucky this time (and probably most of the time), and it worked.

like image 100
abelenky Avatar answered Nov 03 '22 11:11

abelenky