Re: strncpy clarify result may not be null terminated

Jonny Grant
2023-11-10T17:47:16Z

On 09/11/2023 11:38, Alejandro Colomar wrote:
> Hi Jonny,
>
> On Thu, Nov 09, 2023 at 10:31:49AM +0000, Jonny Grant wrote:
>>> Probably the only way to solve the cleverness issue for good is to have an
>>> immediately-available, foolproof, performant set of string functions that
>>> are extremely straightforward to understand and use, flexible enough for
>>> any use case, and generally agreed to be the first choice for string
>>> manipulation.
>>
>> What's the best standardized function for C string copying in your
>
> strlcpy(3) will soon be standard. POSIX.1-202x (Issue 8) will add it,
> which is why it's been added recently to glibc. Hopefully, ISO C3x will
> follow (yeah, it's not like tomorrow).
>
>> opinion? They all seem to have drawbacks, strlcpy truncates (I'd
>> rather it rejected if it didn't have enough buffer - could cause
>> issues if the meaning of the string changed due to truncation, eg if
>> it was a file path). Other alternative functions aren't widely in use.
>
> If you are consistent in checking the return value of strlcpy(3) and
> reporting an error, it's the best standard alternative nowadays.
> snprintf(3), except for using int instead of size_t, has an equivalent
> API, and is in C99, in case that means something.
>
> If you would want to write something based on Michael Kerrisk's article,
> you could do this:
>
> ssize_t
> strxcpy(char *restrict dst, char *restrict src, size_t dsize)
> {
> if (strlen(src) < dsize)
> return -1;
>
> strcpy(dst, src);
> }
>
> You may also want to calculate 'dsize' automagically, to avoid human
> error, in case it's an array, so you could write a macro on top of it:
>
> #define STRXCPY(dst, src) strxcpy(dst, src, ARRAY_SIZE(dst))
>
> These are just small wrappers over standard functions, so you shouldn't
> have problems adding them to your project.
>
> This is my long term plan for shadow-utils, indeed. I'm first
> transforming strncpy(3) calls into strlcpy(3) to remove the superfluous
> padding, and later will use this strxcpy() to remove the truncated
> strings to avoid misinterpretation.
>
> Cheers,
> Alex
>
>>
>> Kind regards, Jonny
>

Yes, I like to look for a libc library function before writing my own wrapper, but I would consider something like strxcpy.

snprintf will truncate if not enough space, but will then return the number of bytes that would have been written had there not been truncation. So one could use snprintf on an array buffer on the stack, and then if truncation, discard the buffer and return an error, otherwise carry on using the string (that wasn't truncated).

Re strlcpy I see BSD man page gives some examples how to check for truncation by strlcpy. Perhaps examples could be added to linux kernel man page.
https://man.freebsd.org/cgi/man.cgi?query=strlcat&sektion=3

Kind regards, Jonny