Here is an example code to demonstrate the problem:
#include <stdio.h>
#include <string.h>
int main()
{
char a[] = "01234567";
strncpy(a, "foobar", 4);
printf("%.8s\n", a);
return 0;
}
Here is the output: $ cc -std=c89 -Wall -Wextra -pedantic foo.c && ./a.out
foob4567
A C89-conforming alternative I use is a macro like this that guarantees '\0'-termination as the first thing: #define strcp(a, b, c) (a[0] = '\0', strncat(a, b, c - 1))
An example from my code: https://github.com/susam/uncap/blob/master/uncap.c#L78-L87Here is how to use it:
#include <stdio.h>
#include <string.h>
#define strcp(a, b, c) (a[0] = '\0', strncat(a, b, c - 1))
int main()
{
char a[] = "01234567";
strcp(a, "foobar", 4);
printf("%.8s\n", a);
return 0;
}
Here is the output: $ cc -std=c89 -Wall -Wextra -pedantic foo.c && ./a.out
fooE.g. suppose we write something like
char* buf = strcp(((char*)malloc(4)), "foobar", 4);
expecting this to copy the beginning of the string "foobar" into a newly-allocated 4-byte buffer. Oops... this will actually call malloc twice (leaking the first buffer), and it won't have written the intended '\0' into the buffer that actually ends up getting used, so all bets are off...If strcp were a function, its first argument would be evaluated just once, and it would work as intended.
> Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.
No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).
Here's a good explanation from Raymond Chen: https://devblogs.microsoft.com/oldnewthing/?p=36773
Finding use of strlcpy in a program is a red warning of sloppy code.
There are good reasons it was kept out of glibc for so long.
The first step is to compile the C program with a C++ compiler. Next, start making improvements. If you skip the first step, the ceiling on improvements is limited.
And when it's not, the ceiling on improvements is limited.
(See also https://linux.die.net/man/3/strncpy )