[PATCH v3] Implement strlcpy [BZ #178]
Paul Eggert
eggert@cs.ucla.edu
Thu Oct 29 21:51:00 GMT 2015
I'd rather we didn't add strlcpy to glibc, for reasons already
discussed. If consensus goes against me, the patch still needs some
work. I don't recall the details of our previous discussion; at the risk
of reraising old issues here are some comments:
* If strlen(SRC) < DESTLEN, the documentation should clearly state that
the contents of the bytes DEST[strlen(SRC) + 1] through DEST[DESTLEN -
1] are preserved. The current documentation can be plausibly read that
way, but it's not explicit.
* The proposed documentation can easily be misread as implying that
strlcpy (DEST, SRC, DESTLEN) does O(DESTLEN) work, which is incorrect:
strlcpy always does O(strlen(SRC)) work. This point should be made
clearly. This is not merely a performance issue: it should be made
crystal-clear that SRC must be null-terminated even if the source's
trailing null byte is way after the bytes that strlcpy copies to DEST.
* strlcpy's name should be prefixed by '__' by default. The names
strlcpy and strlcpy_chk are both in the implementation namespace, and
it's odd to have one without leading underscores and the other with
them. I suggest a more cautious approach, in which both names are
prefixed with '__' and unprefixed strlcpy is provided to the user only
when GNU or BSD extensions are requested via _GNU_SOURCE etc. This is
less likely to break existing applications. It's true that POSIX and the
C standard allow glibc to add str* names of all sorts, but it doesn't
hurt to be realistic here about the user code that's undoubtedly out there.
* strlcpy's implementation should use memmove instead of memcpy. The
main motivations for strlcpy are safety and consistency and avoiding
errors. memmove obviously supports these goals better than memcpy
does. Efficiency is not a major concern with strlcpy (if it were,
strlcpy wouldn't be O(strlen(SRC))).
> +Not guaranteeing null termination and always overwriting the entire
> +destination buffer makes @code{strncpy} rarely useful, but this behavior
> +is specified by the @w{ISO C} standard. See @code{strlcpy} below for an
> +alternative.
This quote is confusing, as it imples that strlcpy guarantees null
termination, which strlcpy does not. I suggest rewording it to something
like the following: "Often @code{strncpy} is not what you want, because
it does not null-terminate the destination if the destination is smaller
than the source, it always overwrites the entire destination buffer, it
may truncate the destination, and it has undefined behavior if the
source and destination overlap. For alternatives, see the documentation
below for @code{strlcpy}."
We can pair this with similar phrasing under strlcpy -- something like
the following perhaps (this wording assumes strlcpy is changed to use
memmove):"Often @code{strlcpy} is not what you want, because it does not
null-terminate the destination if the destination's size is zero,it can
leave junk data behind in the destination, it can do useless work when
the source is long and the destination short, and it may truncate the
destination. Although one alternative is @code{strncpy}, it is usually
better to use dynamic memory allocation and functions such as
@code{strdup} or @code{asprintf} to construct strings."
More information about the Libc-alpha
mailing list