2

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 ?

  • _"how can an character array, arr2 of size 5 accommodate another a size of 20 ?"_ is answered by undefined behavior. But you should double check what your output is showing against your assertions. _"size of the arr1 is just 5"_. but your outout shows it correctly as 16 – ryyker Jun 21 '22 at 14:06
  • 1
    The size of the arrays don't change. Just like when you overfill your cup and it spills everywhere.. your cup is still the same size, you just have a mess. Overflowing a buffer is the digital equivalent. – yano Jun 21 '22 at 14:22
  • 1
    @yano, I couldn't have thought of a better metaphor. – Daniel Walker Jun 21 '22 at 14:23
  • @hariharasankar, you're confusing `sizeof` with `strlen`. – Daniel Walker Jun 21 '22 at 14:24
  • 1
    Many thousands of C beginners before you also thought they had found "really unusual behavior"... why a good teacher or book needs to explain what undefined behavior means. [What is undefined behavior and how does it work?](https://software.codidact.com/posts/277486) – Lundin Jun 21 '22 at 14:26
  • 1
    Also `strncpy` should be avoided for any purpose. See [Is strcpy dangerous and what should be used instead?](https://software.codidact.com/posts/281518) which explains the only purpose why `strncpy` ever existed, among other things. – Lundin Jun 21 '22 at 14:27
  • [this](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794) is one of the more colorful metaphors on SO about undefined behavior. It's tagged C++ and talking about an entirely different type of UB, but all the concepts and colorful language apply. The point is anything can happen with UB, including to appear to "work" as you've seen. Next time it may not. If you change systems, compilers, compiler flags, it may not. You choose to live in an unpredictable world by invoking UB. – yano Jun 21 '22 at 14:40
  • 1
    Note that `strncpy()` is not guaranteed to write a nul terminator. You must also have `arr2[4] = '\0';` after the call. – Weather Vane Jun 21 '22 at 14:43

1 Answers1

2

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.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • There are only 5 character spaces in `arr2`, then how can the character array `arr1` with 15 character spaces fits in `arr2`. – hari hara sankar Jun 21 '22 at 14:19
  • 1
    @hariharasankar The problem is that it does not fit in the array arr2. The function knows nothing about the size of the array arr2. So it overwrites the memory beyond the array. As a result the program has undefined behavior. – Vlad from Moscow Jun 21 '22 at 14:21
  • 1
    @hariharasankar What happens if you hammer a 20cm nail through a 10cm wall with a picture frame on the other side? The wall is still 10cm think (array size didn't change). The nail is still 20cm long (string length didn't change). Nothing was stopping you, but now you have a nail sticking out of your wall and a picture frame with a hole in it (corrupted memory and undefined behavior). Oops. – CherryDT Jun 21 '22 at 14:36
  • I can understand now very clearly. Thanks everyone and your amazing metaphors. – hari hara sankar Jun 21 '22 at 14:38