Re: strncpy clarify result may not be null terminated

Paul Eggert
2023-11-10T22:14:17Z

[-- Attachment #1: Type: text/plain, Size: 1133 bytes --]

On 2023-11-10 11:52, Alejandro Colomar wrote:

> Do you have any numbers?

It depends on size of course. With programs like 'tar' (one of the few
programs that actually needs something like strncpy) the destination
buffer is usually fairly small (32 bytes or less) though some of them
are 100 bytes. I used 16 bytes in the following shell transcript:

$ for i in strnlen+strcpy strnlen+memcpy strncpy stpncpy strlcpy; do
echo; echo $i:; time ./a.out 16 100000000 abcdefghijk $i; done

strnlen+strcpy:

real 0m0.411s
user 0m0.411s
sys 0m0.000s

strnlen+memcpy:

real 0m0.392s
user 0m0.388s
sys 0m0.004s

strncpy:

real 0m0.300s
user 0m0.300s
sys 0m0.000s

stpncpy:

real 0m0.326s
user 0m0.326s
sys 0m0.000s

strlcpy:

real 0m0.623s
user 0m0.623s
sys 0m0.000s

... where a.out was generated by compiling the attached program with gcc
-O2 on Ubuntu 23.10 64-bit on a Xeon W-1350.

I wouldn't take these numbers all that seriously, as microbenchmarks
like these are not that informative these days. Still, for a typical
case one should not assume strncpy must be slower merely because it has
more work to do; quite the contrary.

[-- Attachment #2: strncpy-bench.c --]
[-- Type: text/x-csrc, Size: 1090 bytes --]

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

int
main (int argc, char **argv)
{
if (argc != 5)
return 2;
long bufsize = atol (argv[1]);
char *buf = malloc (bufsize);
long n = atol (argv[2]);
char const *a = argv[3];
if (strcmp (argv[4], "strnlen+strcpy") == 0)
{
for (long i = 0; i < n; i++)
{
if (strnlen (a, bufsize) == bufsize)
return 1;
strcpy (buf, a);
}
}
else if (strcmp (argv[4], "strnlen+memcpy") == 0)
{
for (long i = 0; i < n; i++)
{
size_t alen = strnlen (a, bufsize);
if (alen == bufsize)
return 1;
memcpy (buf, a, alen + 1);
}
}
else if (strcmp (argv[4], "strncpy") == 0)
{
for (long i = 0; i < n; i++)
if (strncpy (buf, a, bufsize)[bufsize - 1])
return 1;
}
else if (strcmp (argv[4], "stpncpy") == 0)
{
for (long i = 0; i < n; i++)
if (stpncpy (buf, a, bufsize) == buf + bufsize)
return 1;
}
else if (strcmp (argv[4], "strlcpy") == 0)
{
for (long i = 0; i < n; i++)
if (strlcpy (buf, a, bufsize) == bufsize)
return 1;
}
else
return 2;
}