-1

I want to write a simple program and I want it to fail to understand strcpy and proper memory management but it still executes. I am trying to dynamically allocate memory (with malloc) for a string enough for only 3 (or anything less than the source) chars to be used as the destination and allocate less memory (or chars) than the string array of the source which is allocated on the stack (string of 10 chars). It copies and prints the content no matter how I define the memory allocation. what's the mistake here?

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

int main()
{
    char *ch = NULL;
    char name[10] = "something";
    ch = (char*)malloc(3 * sizeof(char));
    strcpy(ch, name);
    
    printf("%s\n", name);
    free(ch);
    ch = NULL;
}
Onederfoo
  • 77
  • 1
  • 1
  • 7
  • "I want it to fail to understand strcpy and proper memory management but it still executes" Huh...? – Lundin Sep 30 '20 at 09:47

2 Answers2

2

The mistake here is you're relying on undefined behaviour.

Compiler does not throw any error for out-of-bound (or invalid) memory access, but when your program try to access an invalid memory, the behaviour is undefined.

For strcpy(), in case the destination buffer is not large enough to hold the content from the source, including the null-terminator, then essentially you'll be accessing memory out of bound, which is invalid, causing the undefined behaviour. It's the responsibility of the programmer to ensure the destination buffer has enough space to store the string to be copied.

From the man page

The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest. The strings may not overlap, and the destination string dest must be large enough to receive the copy.[....]

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
2

The behaviour of writing array out of bounds is undefined. On my computer, without optimization:

% gcc overflow.c
% ./a.out    
something

and with optimization enabled

% gcc -O3 overflow.c
In file included from /usr/include/string.h:495,
                 from overflow.c:2:
In function ‘strcpy’,
    inlined from ‘main’ at overflow.c:10:5:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:90:10: warning: 
     ‘__builtin___memcpy_chk’ writing 10 bytes into a region of size 3
     overflows the destination [-Wstringop-overflow=]
   90 |   return __builtin___strcpy_chk (__dest, __src, __bos (__dest));
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
% ./a.out       
*** buffer overflow detected ***: terminated
[2]    240741 abort (core dumped)  ./a.out

The reason is that with optimization GCC will actually propagate the array sizes and will produce machine code equivalent to

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

int main(void)
{
    char name[10] = "something";
    char *ch = malloc(3);
    __memcpy_chk(ch, name, sizeof name, 3);
    puts(name);
    free(ch);
}

and __memcpy_chk will check the length of the destination buffer, and since it is exceeded, the program will abort at runtime.

Always when developing, remember to test your code optimizations enabled too!