char* buf = (char*)malloc(sizeof(char) * 11);
for (int i = 0; i < 5; i )
buf[i] = '?';
strcpy_s(buf 5, sizeof(char) * 11, "apple");
buf[10] = '\0';
printf(buf);
free(buf);
I have the code above. It says "heap corruction detected" when buf is freed. I want to use strcpy_s to write to the last 5 characters of buf. From what I read and understood, the size argument should be the size of the destination buffer but I also tried doing
strcpy_s(buf 5, 5, "apple");
But in this case it says buffer is too small. What should I do?
CodePudding user response:
strcpy_s(buf 5, sizeof(char) * 11, "apple");
tells strcpy_s
there are 11 bytes available at buf 5
. That is false; 11 bytes were reserved at the location where buf
points. Starting from buf 5
, there are only 6 bytes available.
This strcpy_s
overruns the array and writes into other memory, corrupting the so-called heap. The reason for this is that, although one might think strcpy_s
copies individual bytes until a terminating null character is seen, the specification for the routine allows it to use the entire destination buffer regardless of the length of the source string. Specifically, C 2018 K.3.7.1.4 5 says:
All elements following the terminating null character (if any) written by
strncpy_s
in the array ofs1max
characters pointed to bys1
take unspecified values whenstrncpy_s
returns a nonzero value.
The purpose of that is to allow an optimized implementation of strncpy_s
to copy large groups of data than individual bytes.
(One might wonder how one can avoid overrunning the terminating null in the source array when copying such groups of data. An answer for this is that, in common C implementations, it is safe to copy aligned words because the memory protections operate in page-aligned units. So a strcpy_s
implementation may copy whole aligned words from the source to the destination as long as they fit into the destination and no null character has yet been seen in a word.)