Re: strncpy clarify result may not be null terminated

Paul Eggert
2023-11-12T20:49:48Z

[dropping libc-alpha since this is only about the man pages]

On 2023-11-12 02:59, Alejandro Colomar wrote:

> I think the man-pages should go
> ahead and write wrapper functions such as strtcpy() and stpecpy()
> aound libc functions; these wrappers should provide a fast and safe
> starting point for most programs.

It's OK for man pages to give these in EXAMPLES sections. However, the
man pages currently go too far in this direction. Currently, if I type
"man stpecpy", I get a man page with a synopsis and it looks to me like
glibc supports stpecpy(3) just like it supports stpcpy(3). But glibc
doesn't do that, as stpecpy is merely a man-pages invention: although
the source code for stpecpy is in the EXAMPLES section of
string_copying(7), you can't use stpecpy in an app without
copy-and-pasting the man page's source into your code.

It's not just stepecpy. For example, there is no ustr2stp function in
glibc, but "man ustr2stp" acts as if there is one.

The man pages should describe the library that exists, not the library
that some of us would rather have.

> It's true that memcpy(3) is the fastest function one can use, but it
> requires the programmer to be rather careful with the lengths of the
> strings. I don't think keeping track of all those little details is
> what the common programmer should do.

Unfortunately, C is not designed for string use that's that convenient.
If you want safe and efficient use of possibly-long C strings, keeping
track of lengths is generally the best way to do it.

>> glibc/strlcpy.c __strlcpy() is there a reason when truncating it overwrites the last byte, twice?
>>
>> memcpy (dest, src, size);
>> dest[size - 1] = '\0';
>
> -1's in the source code make up for off-by-one bugs.

The "dest[size - 1] = '\0';" is there because strlcpy(dst, src, sz) is
defined to null-terminate the result if sz!=0, so that particular "-1"
isn't a bug. (Perhaps you meant that the strlcpy spec itself is buggy?
It wasn't clear to me.)

That "last byte, twice" question is: why is the last argument to memcpy
"size" and not "size - 1" which would be equally correct? The answer is
performance: memcpy often works faster when copying a number of bytes
that is a multiple of a smallish power of two, and "size" is more likely
than "size - 1" to be such a multiple.