Search code examples
arrayscc-stringsbuffer-overflowstrncpy

Confusion of memory in buffer overflow while using strncpy()?


Scope: I have been trying to learn how does buffer overflow occur when using the strncpy function in C and I found this really unusual behavior.

I have two character array as arr1 and arr2. I am trying to move 20 bytes of data from the arr1, an array of size 16 to the arr2 of size 5. Based on my understanding this should trigger a buffer overflow, but I found that the length of string stored in arr2 increases to accommodate the string, but the size of array remains the same.

#include<stdio.h>
#include<string.h>
int main(){
    char arr1[]="Buffer overflow";
    char arr2[5];
    printf("Size of array1 %d\n",sizeof(arr1));
    strncpy(arr2,arr1,20);
    printf("\nAfter copy\n");
    printf("Length of arr2: %d\n",strlen(arr2));
    printf("Size of arr2: %d\n",sizeof(arr2));
    printf("Arr2: %s\n",arr2);
    return 0;
}



I found the following output really surprising,

Size of array1 16

After copy
Length of arr2: 15
Size of arr2: 5
Arr2: Buffer overflow

Problem: How can the length of arr2 be 15 when the size of the arr2 is just 5 and how can an character array, arr2 of size 5 accommodate another a size of 20 ?


Solution

  • The program has undefined behavior because this call

    strncpy(arr2,arr1,20);
    

    overwrites the memory outside the character array arr2. The function knows nothing about the size of the array arr2. (Bear in mind that the array arr2 used as a function argument is implicitly converted to a pointer to its first element.) It trusts the caller of the function that the number of copied characters is specified correctly. It is the responsibility of the caller of the function to guarantee a correct work of the function.

    The size of the array was not changed and this output confirms that

    Size of arr2: 5
    

    This call

    printf("Length of arr2: %d\n",strlen(arr2));
    

    does not output the size of the array arr2. It outputs the length of the copied string "Buffer overflow".

    Pay attention to that you have to use the conversion specifier %zu with objects of the type size_t instead of the conversion specifier %d.