Message ID | 56376656.1000600@redhat.com |
---|---|
State | New |
Headers | show |
On Mon, Nov 02, 2015 at 02:34:14PM +0100, Florian Weimer wrote: > On 10/29/2015 10:50 PM, Paul Eggert wrote: > > 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. > > I don't want to give any guarantees other implementations do not provide. I agree strongly with this principle, but I do think this is guaranteed by other implementations, in terms of both actual behavior and the implicit requirement not to clobber memory the function is not specified to clobber. If there's doubt we should clarify with the authors of the original. Am I correct in thinking the OpenBSD version is the original? > > * 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))). > > The original OpenBSD implementation does not handle all overlapping > buffers in the same way memmove would. Most BSDs now specify the > restrict qualify in the function prototype and documentation. > > The existing *_chk functions do not check for overlapping inputs, and > they even have restrict pointer arguments, so such checks could be > futile anyway. If we want to change this approach, I think this should > be a separate discussion. (Right now, there is memstomp for this.) Agreed, but I just want to add that I don't think the restrict qualifier precludes testing for overlap. None of the requirements imposed by restrict apply unless you actually access an object based on the restrict-qualified pointer(s). So any tests that take place before dereferencing should be safe against being optimized out. Rich
On 11/03/2015 08:15 AM, Rich Felker wrote: > I do think this is > guaranteed by other implementations, in terms of both actual behavior > and the implicit requirement not to clobber memory the function is not > specified to clobber. I don't see any such implicit requirement, so I agree with Florian here. My impression all along has been that when a function is given an output buffer, it can write whatever it likes to the output buffer, so long as the buffer has the proper value when the function returns. In particular, the caller can't expect the buffer's irrelevant bytes (i.e., bytes not part of the output value) to be preserved. I see nothing in POSIX or in the BSD documentation that requires preservation of irrelevant bytes, either for strlcpy or for POSIX functions in general. So, for example, on POSIX implementations where struct timespec has padding bytes, a caller cannot expect clock_gettime(CLOCK_REALTIME, &ts) to preserve ts's padding bytes, because POSIX doesn't say irrelevant bytes are preserved. > If there's doubt we should clarify with the authors of the original. This is not an issue that OpenBSD implementers can unilaterally decide now. "Ooops, there's an nonobvious strlcpy feature that we forgot to write down, but all implementations are required to support it anyway."?!? Sorry, but no. That shouldn't work for clock_gettime, and it shouldn't work for strlcpy either.
On Tue, Nov 03, 2015 at 03:12:47PM -0800, Paul Eggert wrote: > On 11/03/2015 08:15 AM, Rich Felker wrote: > >I do think this is > >guaranteed by other implementations, in terms of both actual behavior > >and the implicit requirement not to clobber memory the function is not > >specified to clobber. > > I don't see any such implicit requirement, so I agree with Florian here. In that case, strlcpy can also assign environ=NULL and change the disposition of all signal handlers to exec /usr/games/hack. Jokes aside, a function that can have random side effects aside from what it's specified to do is unusable. > My impression all along has been that when a function is given an > output buffer, it can write whatever it likes to the output buffer, > so long as the buffer has the proper value when the function > returns. This is not the case, at least not for any of the standard functions. Read the specifications. There is no text allowing such behavior. > In particular, the caller can't expect the buffer's > irrelevant bytes (i.e., bytes not part of the output value) to be > preserved. This is wrong, and the fact that it's wrong is actually essential to some usage patterns like using fgets to read files that may contain embedded nuls. > I see nothing in POSIX or in the BSD documentation that > requires preservation of irrelevant bytes, either for strlcpy or for > POSIX functions in general. So, for example, on POSIX > implementations where struct timespec has padding bytes, a caller > cannot expect clock_gettime(CLOCK_REALTIME, &ts) to preserve ts's > padding bytes, because POSIX doesn't say irrelevant bytes are > preserved. Padding bytes are different; they're explicitly permitted to be altered by any stores. Moreover, in the case of clock_gettime, the specified behavior is storing a structure. This would allow any implementation-defined additional members in the structure to be changed since they are also part of the structure. > >If there's doubt we should clarify with the authors of the original. > > This is not an issue that OpenBSD implementers can unilaterally > decide now. "Ooops, there's an nonobvious strlcpy feature that we > forgot to write down, but all implementations are required to > support it anyway."?!? Sorry, but no. That shouldn't work for > clock_gettime, and it shouldn't work for strlcpy either. It's not written down because it's obvious. If all implementations satisfy the requirement (which they do, because it's obvious, and you'd have to go out of your way to do something malicious in order not to satisfy it) then there is no problem with clarifying this. Rich
Rich Felker wrote: > the fact that it's wrong is actually essential to > some usage patterns like using fgets to read files that may contain > embedded nuls. Thanks, that's a usage pattern I wasn't familiar with. However, among other things the glibc manual explicitly says that fgets shouldn't be used in that situation, which suggests the ice is quite thin here. So even if POSIX says what you are asserting (I haven't seen specific citations, so I'm still skeptical), as a practical matter applications should not assume that irrelevant bytes in output buffers are preserved. As far as strlcpy goes perhaps the manual should merely say that it's unspecified what happens to destination bytes after the trailing NUL. We can always specify it later, should POSIX make things clear. I doubt whether applications care much one way or another.
On Tue, Nov 03, 2015 at 06:50:40PM -0800, Paul Eggert wrote: > Rich Felker wrote: > >the fact that it's wrong is actually essential to > >some usage patterns like using fgets to read files that may contain > >embedded nuls. > > Thanks, that's a usage pattern I wasn't familiar with. However, > among other things the glibc manual explicitly says that fgets > shouldn't be used in that situation, which suggests the ice is quite > thin here. So even if POSIX says what you are asserting (I haven't > seen specific citations, so I'm still skeptical), as a practical > matter applications should not assume that irrelevant bytes in > output buffers are preserved. Not even POSIX is needed for this; it's merely ISO C: "The fgets function reads at most one less than the number of characters specified by n from the stream pointed to by stream into the array pointed to by s. No additional characters are read after a new-line character (which is retained) or after end-of-file. A null character is written immediately after the last character read into the array." n is merely a bound on the number of characters to be read; while the buffer is usually at least n characters long, there's not even a requirement that it need be; for situations where the application controls the contents of a file, the behavior could be well-defined even if the buffer is smaller than n. > As far as strlcpy goes perhaps the manual should merely say that > it's unspecified what happens to destination bytes after the > trailing NUL. We can always specify it later, should POSIX make > things clear. I doubt whether applications care much one way or > another. There's certainly existing code that relies on strcpy not clobbering anything past the strlen(src)+1 bytes it writes. Naturally strcpy _can't_ do this because it has no way of knowing the dest buffer size. But to be able to use strlcpy as a safer drop-in replacement in such code, it would need to preserve this property. Rich
On 11/04/2015 04:23 AM, Rich Felker wrote: > There's certainly existing code that relies on strcpy not clobbering > anything past the strlen(src)+1 bytes it writes. Naturally strcpy > _can't_ do this because it has no way of knowing the dest buffer size. > But to be able to use strlcpy as a safer drop-in replacement in such > code, it would need to preserve this property. Good. I'm now convinced that there is such a requirement for strcpy, fgets and so on. I checked our documentation and the standard for strcpy and fgets, and we do not explicitly specify this behavior (although I agree it is implicit). My question is whether we should specify this explicitly for strlcpy. It would give the impression that strlcpy is special in this regard, but it really is not. Florian
On Wed, Nov 04, 2015 at 02:11:25PM +0100, Florian Weimer wrote: > On 11/04/2015 04:23 AM, Rich Felker wrote: > > There's certainly existing code that relies on strcpy not clobbering > > anything past the strlen(src)+1 bytes it writes. Naturally strcpy > > _can't_ do this because it has no way of knowing the dest buffer size. > > But to be able to use strlcpy as a safer drop-in replacement in such > > code, it would need to preserve this property. > > Good. I'm now convinced that there is such a requirement for strcpy, > fgets and so on. I checked our documentation and the standard for > strcpy and fgets, and we do not explicitly specify this behavior > (although I agree it is implicit). My question is whether we should > specify this explicitly for strlcpy. It would give the impression that > strlcpy is special in this regard, but it really is not. I'm fine with omitting explicit documentation (which I agree would imply strlcpy is special and raise confusion about the general principle) as long as there's consensus that this is part of the interface contract. I'd like to see some general language added to the glibc docs explaining this at some point. Rich
On 11/04/2015 05:11 AM, Florian Weimer wrote: > My question is whether we should > specify this explicitly for strlcpy. It would give the impression that > strlcpy is special in this regard, but it really is not. Not a problem, we can add a phrase to avoid giving that impression. Something like "Like other string-copying functions but unlike strncpy, strlcpy does not modify the part of the destination buffer that follows the trailing null byte."
On 11/04/2015 11:12 AM, Paul Eggert wrote: > On 11/04/2015 05:11 AM, Florian Weimer wrote: >> My question is whether we should specify this explicitly for >> strlcpy. It would give the impression that strlcpy is special in >> this regard, but it really is not. > Not a problem, we can add a phrase to avoid giving that impression. > Something like "Like other string-copying functions but unlike > strncpy, strlcpy does not modify the part of the destination buffer > that follows the trailing null byte." Agreed. The bytes that fall outside of the API contract should be unmodified. Doesn't this also have implications in concurrency? Consider the remainder of @var{to} is being operated upon in parallel. In the @code{race} section of intro.texi we talk briefly about how users need to take care with memory buffers passed into functions, but at the same time we must be exceedingly clear on our end what we do with those buffers. Should we forbid reads from parts of @var{to} that are not part of the API contract? Likewise there is also an API contract issue with reads of @var{from} since it forbids concurrent writes to @var{from} because the implementation has to compute the size of @var{from} by looking for \0, and thus explicit locking has to be used to protect @var{from} but not @var{to}, and this can't be easily fixed (follows logically from the definition of the API). Thoughts? Cheers, Carlos.
Florian, My first question is: When are you going to implement strlcat? :-) Thank you for implementing strlcpy. I think this and strlcat are sufficiently used BSD APIs that we need them in glibc to avoid duplication at the application. Worse those duplications may be poorly implemented or have security flaws. Centralizing these in glibc is the right way forward. Unlike C11's Annex K which was IMO never well adopted and which has serious usability issues, the strlcpy and strlcat APIs are better. Overall this looks perfect. My only quibbles are that we should be documenting better the invariants we are testing e.g. a few more comments. > 2015-11-02 Florian Weimer <fweimer@redhat.com> > > [BZ #178] > * string/Makefile (routines): Add strlcpy. > (tests): Add tst-strlcpy. > * string/Versions (2.21): Export strlcpy. > * string/strlcpy.c: New file. > * string/tst-strlcpy.c: Likewise. > * include/string.h (strlcpy): Declare as hidden. > * manual/string.texi (Copying and Concatenation): Document > strlcpy. Update strncpy documentation. > * debug/Makefile (routines): Add strlcpy_chk. > * debug/Versions (2.21): Export __strlcpy_chk. > * debug/tst-chk1.c (doit): Test strlcpy. > * debug/strlcpy_chk.c: New file. > * sysdeps/*/libc.abilist: Add strlcpy, __strlcpy_chk. > > diff --git a/NEWS b/NEWS > index 0831d35..af7e375 100644 > --- a/NEWS > +++ b/NEWS > @@ -23,6 +23,8 @@ Version 2.23 > 19074, 19076, 19077, 19078, 19079, 19085, 19086, 19088, 19094, 19095, > 19124, 19125, 19129, 19134, 19137, 19156, 19174, 19181. > > +* The GNU C Library now includes an implementation of strlcpy. Feel free to include a "Contributed by" here in the NEWS section. e.g. Contributed by Florian Weimer (Red Hat). It acknowledges the work done by the author and the corporate support. > + > * A defect in the malloc implementation, present since glibc 2.15 (2012) or > glibc 2.10 via --enable-experimental-malloc (2009), could result in the > unnecessary serialization of memory allocation requests across threads. > diff --git a/debug/Makefile b/debug/Makefile > index a383417..f6cebab 100644 > --- a/debug/Makefile > +++ b/debug/Makefile > @@ -30,6 +30,7 @@ headers := execinfo.h > routines = backtrace backtracesyms backtracesymsfd noophooks \ > memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \ > strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \ > + strlcpy_chk \ OK. > sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ > printf_chk fprintf_chk vprintf_chk vfprintf_chk \ > gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \ > diff --git a/debug/Versions b/debug/Versions > index 0482c85..60a7aed 100644 > --- a/debug/Versions > +++ b/debug/Versions > @@ -55,6 +55,9 @@ libc { > GLIBC_2.16 { > __poll_chk; __ppoll_chk; > } > + GLIBC_2.23 { > + __strlcpy_chk; > + } OK. > GLIBC_PRIVATE { > __fortify_fail; > } > diff --git a/debug/strlcpy_chk.c b/debug/strlcpy_chk.c > new file mode 100644 > index 0000000..a13bcfe > --- /dev/null > +++ b/debug/strlcpy_chk.c > @@ -0,0 +1,30 @@ > +/* Fortified version of strlcpy. > + Copyright (C) 2015 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <string.h> > +#include <memcopy.h> > + > +size_t > +__strlcpy_chk (char *__restrict s1, const char *__restrict s2, > + size_t n, size_t s1len) > +{ Despite the simplicity I think this should have a comment about the invariant being tested. e.g. /* The compiler determined size of the destination should not be smaller than the user provided size of the destination. */ > + if (__glibc_unlikely (s1len < n)) > + __chk_fail (); > + > + return strlcpy (s1, s2, n); > +} > diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c > index bded583..0805a85 100644 > --- a/debug/tst-chk1.c > +++ b/debug/tst-chk1.c > @@ -415,6 +415,10 @@ do_test (void) > strncpy (a.buf1 + (O + 6), "X", l0 + 4); > CHK_FAIL_END > + CHK_FAIL_START > + strlcpy (buf, "", sizeof (buf) + 1); > + CHK_FAIL_END OK. > + > # if !defined __cplusplus || defined __va_arg_pack > CHK_FAIL_START > sprintf (a.buf1 + (O + 7), "%d", num1); > diff --git a/include/string.h b/include/string.h > index a684fd9..82413af 100644 > --- a/include/string.h > +++ b/include/string.h > @@ -73,6 +73,7 @@ extern __typeof (strncasecmp_l) __strncasecmp_l; > libc_hidden_proto (__mempcpy) > libc_hidden_proto (__stpcpy) > libc_hidden_proto (__stpncpy) > +libc_hidden_proto (strlcpy) > libc_hidden_proto (__rawmemchr) > libc_hidden_proto (__strcasecmp) > libc_hidden_proto (__strcasecmp_l) > diff --git a/manual/string.texi b/manual/string.texi > index 5f8a17e..8eda29a 100644 > --- a/manual/string.texi > +++ b/manual/string.texi > @@ -576,17 +576,52 @@ there is no null terminator written into @var{to}. > > If the length of @var{from} is less than @var{size}, then @code{strncpy} > copies all of @var{from}, followed by enough null characters to add up > -to @var{size} characters in all. This behavior is rarely useful, but it > -is specified by the @w{ISO C} standard. > +to @var{size} characters in all. OK. > > The behavior of @code{strncpy} is undefined if the strings overlap. > > -Using @code{strncpy} as opposed to @code{strcpy} is a way to avoid bugs > +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 which null-terminates the destination string as long as the > +destination buffer does not have length zero. > +@end deftypefun OK. > + > +@comment string.h > +@comment BSD > +@deftypefun size_t strlcpy (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) OK. OpenBSD and FreeBSD document these as "@var{dst}" and "@var{src}" rather than "@var{to}" and "@var{from}", but the rest of our manual use "to" and "from" so I think this is fine. > +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} > +This function is similar to @code{strcpy}, but copies at most @var{size} > +characters into @var{to}, including the terminating null character. > + > +If the length of @var{from} is equal to or more than @var{size}, then > +@code{strlcpy} copies just the first @samp{@var{size} - 1} characters. ... and the null character? > +As a special case, if @var{size} is zero, no bytes are written to > +@var{to}. > + > +If the length of @var{from} is less than @var{size}, then @code{strlcpy} > +copies all of @var{from}, followed by a single null character. > + > +The return value @var{result} of @code{strlcpy} is the length of the > +string @var{from}. This means that @samp{@var{result} >= @var{size}} is > +true whenever truncation occurs. > + > +The string @var{from} must be null-terminated even if its length exceeds > +that of the destination buffer. The behavior of @code{strlcpy} is > +undefined if the strings overlap or if the source or destination are > +null pointers. > + > +Using @code{strlcpy} as opposed to @code{strcpy} is a way to avoid bugs > relating to writing past the end of the allocated space for @var{to}. > -However, it can also make your program much slower in one common case: > -copying a string which is probably small into a potentially large buffer. > -In this case, @var{size} may be large, and when it is, @code{strncpy} will > -waste a considerable amount of time copying null characters. > +Unlike @code{strncpy}, @code{strlcpy} ensures that the destination > +string is always null-terminated (unless the buffer size is zero), and > +it does not fill the remaining part of the buffer with null characters. > + > +@strong{Note:} GNU programs should not use statically sized buffers for > +storing strings. @xref{Semantics, , Writing Robust Programs, standards, > +The GNU Coding Standards}. Instead of using @code{strlcpy}, it is > +usually better to use dynamic memory allocation and functions such as > +@code{strdup} or @code{asprintf} to construct strings. > @end deftypefun OK. > > @comment wchar.h > diff --git a/string/Makefile b/string/Makefile > index ebe9354..0d1fb52 100644 > --- a/string/Makefile > +++ b/string/Makefile > @@ -41,7 +41,7 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ > addsep replace) \ > envz basename \ > strcoll_l strxfrm_l string-inlines memrchr \ > - xpg-strerror strerror_l > + xpg-strerror strerror_l strlcpy OK. > > strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ > stpcpy stpncpy strcat strchr strcmp strcpy strcspn \ > @@ -54,7 +54,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ > tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ > bug-strtok1 $(addprefix test-,$(strop-tests)) \ > bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \ > - tst-strtok_r bug-strcoll2 > + tst-strtok_r bug-strcoll2 tst-strlcpy OK. > > xtests = tst-strcoll-overflow > > diff --git a/string/Versions b/string/Versions > index 59bf35a..bd00ca1 100644 > --- a/string/Versions > +++ b/string/Versions > @@ -80,4 +80,7 @@ libc { > GLIBC_2.6 { > strerror_l; > } > + GLIBC_2.23 { > + strlcpy; > + } OK. > } > diff --git a/string/bits/string3.h b/string/bits/string3.h > index 4d11aa6..9f28a73 100644 > --- a/string/bits/string3.h > +++ b/string/bits/string3.h > @@ -40,6 +40,7 @@ __warndecl (__warn_memset_zero_len, > # undef stpcpy > # endif > # ifdef __USE_MISC > +# undef strlcpy OK. > # undef bcopy > # undef bzero > # endif > @@ -155,3 +156,29 @@ __NTH (strncat (char *__restrict __dest, const char *__restrict __src, > { > return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest)); > } > + > +#ifdef __USE_MISC > +__warndecl (__warn_strlcpy_size_zero, > + "strlcpy used with a size argument of zero"); > +__warndecl (__warn_strlcpy_size_large, > + "strlcpy used with a size argument which is too large"); > +extern size_t __strlcpy_chk (char *__dest, const char *__src, size_t __n, > + size_t __destlen) __THROW; > + > +__fortify_function size_t > +__NTH (strlcpy (char *__restrict __dest, const char *__restrict __src, > + size_t __len)) > +{ > + if (__builtin_constant_p (__len == 0) && __len == 0) > + { > + __warn_strlcpy_size_zero (); OK. > + return 0; > + } > + if (__builtin_constant_p (__len > __bos (__dest)) && __len > __bos (__dest)) > + __warn_strlcpy_size_large (); OK. > + if (__builtin_constant_p (__bos (__dest) == (size_t) -1) > + && __bos (__dest) == (size_t) -1) > + return strlcpy (__dest, __src, __len); > + return __strlcpy_chk (__dest, __src, __len, __bos (__dest)); > +} > +#endif > diff --git a/string/string.h b/string/string.h > index 3ab7103..92a5d80 100644 > --- a/string/string.h > +++ b/string/string.h > @@ -574,6 +574,13 @@ extern char *stpncpy (char *__restrict __dest, > __THROW __nonnull ((1, 2)); > #endif > > +#ifdef __USE_MISC > +/* Copy at most N characters from SRC to DEST. */ > +extern size_t strlcpy (char *__restrict __dest, > + const char *__restrict __src, size_t __n) > + __THROW __nonnull ((1, 2)); > +#endif > + OK. > #ifdef __USE_GNU > /* Compare S1 and S2 as strings holding name & indices/version numbers. */ > extern int strverscmp (const char *__s1, const char *__s2) > diff --git a/string/strlcpy.c b/string/strlcpy.c > new file mode 100644 > index 0000000..3833a50 > --- /dev/null > +++ b/string/strlcpy.c > @@ -0,0 +1,47 @@ > +/* Copy a null-terminated string to a fixed-size buffer, with length checking. > + Copyright (C) 2015 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <string.h> > + > +#undef strlcpy > + > +size_t > +strlcpy (char *__restrict dest, const char *__restrict src, size_t size) > +{ > + size_t src_length = strlen (src); > + > + if (__glibc_unlikely (src_length >= size)) > + { > + if (size > 0) > + { > + /* Copy the leading portion of the string. The last > + character is subsequently overwritten with the NUL > + terminator, but the destination size is usually a > + multiple of a small power of two, so writing it twice > + should be more efficient than copying an odd number of > + bytes. */ > + memcpy (dest, src, size); > + dest[size - 1] = '\0'; > + } > + } > + else > + /* Copy the string and its terminating NUL character. */ > + memcpy (dest, src, src_length + 1); > + return src_length; OK. > +} > +libc_hidden_def (strlcpy) > diff --git a/string/tst-strlcpy.c b/string/tst-strlcpy.c > new file mode 100644 > index 0000000..b97f591 > --- /dev/null > +++ b/string/tst-strlcpy.c > @@ -0,0 +1,66 @@ > +/* Test the strlcpy function. > + Copyright (C) 2015 Free Software Foundation, Inc. OK. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <http://www.gnu.org/licenses/>. */ > + > +#include <string.h> > +#include <stdlib.h> > +#include <stdio.h> > + > +#define CHECK(cond) \ > + if (!(cond)) \ > + { \ > + printf ("%s:%d: FAIL\n", __FILE__, __LINE__); \ > + exit (1); \ > + } > + > +static int > +do_test (void) > +{ > + struct { > + char buf1[16]; > + char buf2[16]; > + } s; > + This needs more comments. Each of these tests needs a comment explaining the intent of the test, even a succinct comment is worth a lot to a future maintainer reviewing the failed test. > + memset (&s, '@', sizeof (s)); > + CHECK (strlcpy (s.buf1, "Hello!", 0) == 6); > + CHECK (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", sizeof (s)) == 0); > + > + memset (&s, '@', sizeof (s)); > + CHECK (strlcpy (s.buf1, "Hello!", sizeof (s.buf1)) == 6); > + CHECK (memcmp (&s, "Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@", sizeof (s)) == 0); > + > + memset (&s, '@', sizeof (s)); > + CHECK (strlcpy (s.buf1, "Hello, world!!!", sizeof (s.buf1)) == 15); > + CHECK (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", > + sizeof (s)) == 0); > + > + memset (&s, '@', sizeof (s)); > + CHECK (strlcpy (s.buf1, "Hello, world!!!!", sizeof (s.buf1)) == 16); > + CHECK (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", > + sizeof (s)) == 0); > + > + memset (&s, '@', sizeof (s)); > + CHECK (strlcpy (s.buf1, "Hello, world!!!!!!!!", sizeof (s.buf1)) == 20); > + CHECK (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", > + sizeof (s)) == 0); > + > + return 0; > +} > + > +#define TEST_FUNCTION do_test () > +#include "../test-skeleton.c" > + > diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist > index 561441e..9137c51 100644 > --- a/sysdeps/arm/nacl/libc.abilist > +++ b/sysdeps/arm/nacl/libc.abilist > @@ -1834,3 +1834,6 @@ GLIBC_2.22 wprintf F > GLIBC_2.22 write F > GLIBC_2.22 writev F > GLIBC_2.22 wscanf F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > index c1ba62c..62c6412 100644 > --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist > @@ -2081,3 +2081,6 @@ GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.18 _mcount F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist > index 7d2d121..e5bff7e 100644 > --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist > +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist > @@ -1992,6 +1992,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist > index a30b258..5e7f8e9 100644 > --- a/sysdeps/unix/sysv/linux/arm/libc.abilist > +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist > @@ -82,6 +82,9 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.4 GLIBC_2.4 A > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 > diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist > index 571548a..ff90320 100644 > --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist > +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist > @@ -1846,6 +1846,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist > index 87abbbd..ecf1d72 100644 > --- a/sysdeps/unix/sysv/linux/i386/libc.abilist > +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist > @@ -2004,6 +2004,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist > index 1cbdffe..8039f68 100644 > --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist > @@ -1868,6 +1868,9 @@ GLIBC_2.2.6 __nanosleep F > GLIBC_2.2.6 getunwind F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > index 061b5ee..8053211 100644 > --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist > @@ -83,6 +83,9 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.4 GLIBC_2.4 A > GLIBC_2.4 _Exit F > GLIBC_2.4 _IO_2_1_stderr_ D 0x98 > diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > index 91be3d8..d3d9863 100644 > --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist > @@ -1960,6 +1960,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist > index c1b1cad..6fe3aeb 100644 > --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist > +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist > @@ -2081,3 +2081,6 @@ GLIBC_2.18 xprt_register F > GLIBC_2.18 xprt_unregister F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > index 3ef9b99..87de055 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist > @@ -1935,6 +1935,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > index c44ee13..aed7e26 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist > @@ -1933,6 +1933,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > index e8908e4..06d5c94 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist > @@ -1931,6 +1931,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > index c6d1da2..e06e184 100644 > --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist > @@ -1926,6 +1926,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist > index 703979a..c837ec4 100644 > --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist > +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist > @@ -2122,3 +2122,6 @@ GLIBC_2.21 xprt_register F > GLIBC_2.21 xprt_unregister F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > index 90ca484..866c0c5 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist > @@ -1964,6 +1964,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > index a5ecc76..2b647f7 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist > @@ -1969,6 +1969,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist > index c6bea69..b0359b2 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist > @@ -2169,3 +2169,6 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist > index 21e736b..df9a5f5 100644 > --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist > @@ -83,6 +83,9 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 _Exit F > GLIBC_2.3 _IO_2_1_stderr_ D 0xe0 > diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > index d6c037b..12528d0 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist > @@ -1964,6 +1964,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > index 02422da..99d63b4 100644 > --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist > @@ -1865,6 +1865,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist > index 5accb42..5d7baaa 100644 > --- a/sysdeps/unix/sysv/linux/sh/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist > @@ -1850,6 +1850,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > index 0ecba65..eda8cc2 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist > @@ -1956,6 +1956,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > index ce45412..9c72aaf 100644 > --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist > @@ -1894,6 +1894,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist > index 63441e9..50bbb2d 100644 > --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist > @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist > index 212e4d5..51c87cd 100644 > --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist > @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist > index 63441e9..50bbb2d 100644 > --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist > +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist > @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > index afb29dc..60e85dc 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist > @@ -1845,6 +1845,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A > GLIBC_2.2.6 __nanosleep F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. > GLIBC_2.3 GLIBC_2.3 A > GLIBC_2.3 __ctype_b_loc F > GLIBC_2.3 __ctype_tolower_loc F > diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > index 7ac7104..386d4b3 100644 > --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist > @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A > GLIBC_2.18 __cxa_thread_atexit_impl F > GLIBC_2.22 GLIBC_2.22 A > GLIBC_2.22 fmemopen F > +GLIBC_2.23 GLIBC_2.23 A > +GLIBC_2.23 __strlcpy_chk F > +GLIBC_2.23 strlcpy F OK. Cheers, Carlos.
2015-11-02 Florian Weimer <fweimer@redhat.com> [BZ #178] * string/Makefile (routines): Add strlcpy. (tests): Add tst-strlcpy. * string/Versions (2.21): Export strlcpy. * string/strlcpy.c: New file. * string/tst-strlcpy.c: Likewise. * include/string.h (strlcpy): Declare as hidden. * manual/string.texi (Copying and Concatenation): Document strlcpy. Update strncpy documentation. * debug/Makefile (routines): Add strlcpy_chk. * debug/Versions (2.21): Export __strlcpy_chk. * debug/tst-chk1.c (doit): Test strlcpy. * debug/strlcpy_chk.c: New file. * sysdeps/*/libc.abilist: Add strlcpy, __strlcpy_chk. diff --git a/NEWS b/NEWS index 0831d35..af7e375 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,8 @@ Version 2.23 19074, 19076, 19077, 19078, 19079, 19085, 19086, 19088, 19094, 19095, 19124, 19125, 19129, 19134, 19137, 19156, 19174, 19181. +* The GNU C Library now includes an implementation of strlcpy. + * A defect in the malloc implementation, present since glibc 2.15 (2012) or glibc 2.10 via --enable-experimental-malloc (2009), could result in the unnecessary serialization of memory allocation requests across threads. diff --git a/debug/Makefile b/debug/Makefile index a383417..f6cebab 100644 --- a/debug/Makefile +++ b/debug/Makefile @@ -30,6 +30,7 @@ headers := execinfo.h routines = backtrace backtracesyms backtracesymsfd noophooks \ memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \ strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \ + strlcpy_chk \ sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \ printf_chk fprintf_chk vprintf_chk vfprintf_chk \ gets_chk chk_fail readonly-area fgets_chk fgets_u_chk \ diff --git a/debug/Versions b/debug/Versions index 0482c85..60a7aed 100644 --- a/debug/Versions +++ b/debug/Versions @@ -55,6 +55,9 @@ libc { GLIBC_2.16 { __poll_chk; __ppoll_chk; } + GLIBC_2.23 { + __strlcpy_chk; + } GLIBC_PRIVATE { __fortify_fail; } diff --git a/debug/strlcpy_chk.c b/debug/strlcpy_chk.c new file mode 100644 index 0000000..a13bcfe --- /dev/null +++ b/debug/strlcpy_chk.c @@ -0,0 +1,30 @@ +/* Fortified version of strlcpy. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <memcopy.h> + +size_t +__strlcpy_chk (char *__restrict s1, const char *__restrict s2, + size_t n, size_t s1len) +{ + if (__glibc_unlikely (s1len < n)) + __chk_fail (); + + return strlcpy (s1, s2, n); +} diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c index bded583..0805a85 100644 --- a/debug/tst-chk1.c +++ b/debug/tst-chk1.c @@ -415,6 +415,10 @@ do_test (void) strncpy (a.buf1 + (O + 6), "X", l0 + 4); CHK_FAIL_END + CHK_FAIL_START + strlcpy (buf, "", sizeof (buf) + 1); + CHK_FAIL_END + # if !defined __cplusplus || defined __va_arg_pack CHK_FAIL_START sprintf (a.buf1 + (O + 7), "%d", num1); diff --git a/include/string.h b/include/string.h index a684fd9..82413af 100644 --- a/include/string.h +++ b/include/string.h @@ -73,6 +73,7 @@ extern __typeof (strncasecmp_l) __strncasecmp_l; libc_hidden_proto (__mempcpy) libc_hidden_proto (__stpcpy) libc_hidden_proto (__stpncpy) +libc_hidden_proto (strlcpy) libc_hidden_proto (__rawmemchr) libc_hidden_proto (__strcasecmp) libc_hidden_proto (__strcasecmp_l) diff --git a/manual/string.texi b/manual/string.texi index 5f8a17e..8eda29a 100644 --- a/manual/string.texi +++ b/manual/string.texi @@ -576,17 +576,52 @@ there is no null terminator written into @var{to}. If the length of @var{from} is less than @var{size}, then @code{strncpy} copies all of @var{from}, followed by enough null characters to add up -to @var{size} characters in all. This behavior is rarely useful, but it -is specified by the @w{ISO C} standard. +to @var{size} characters in all. The behavior of @code{strncpy} is undefined if the strings overlap. -Using @code{strncpy} as opposed to @code{strcpy} is a way to avoid bugs +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 which null-terminates the destination string as long as the +destination buffer does not have length zero. +@end deftypefun + +@comment string.h +@comment BSD +@deftypefun size_t strlcpy (char *restrict @var{to}, const char *restrict @var{from}, size_t @var{size}) +@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} +This function is similar to @code{strcpy}, but copies at most @var{size} +characters into @var{to}, including the terminating null character. + +If the length of @var{from} is equal to or more than @var{size}, then +@code{strlcpy} copies just the first @samp{@var{size} - 1} characters. +As a special case, if @var{size} is zero, no bytes are written to +@var{to}. + +If the length of @var{from} is less than @var{size}, then @code{strlcpy} +copies all of @var{from}, followed by a single null character. + +The return value @var{result} of @code{strlcpy} is the length of the +string @var{from}. This means that @samp{@var{result} >= @var{size}} is +true whenever truncation occurs. + +The string @var{from} must be null-terminated even if its length exceeds +that of the destination buffer. The behavior of @code{strlcpy} is +undefined if the strings overlap or if the source or destination are +null pointers. + +Using @code{strlcpy} as opposed to @code{strcpy} is a way to avoid bugs relating to writing past the end of the allocated space for @var{to}. -However, it can also make your program much slower in one common case: -copying a string which is probably small into a potentially large buffer. -In this case, @var{size} may be large, and when it is, @code{strncpy} will -waste a considerable amount of time copying null characters. +Unlike @code{strncpy}, @code{strlcpy} ensures that the destination +string is always null-terminated (unless the buffer size is zero), and +it does not fill the remaining part of the buffer with null characters. + +@strong{Note:} GNU programs should not use statically sized buffers for +storing strings. @xref{Semantics, , Writing Robust Programs, standards, +The GNU Coding Standards}. Instead of using @code{strlcpy}, it is +usually better to use dynamic memory allocation and functions such as +@code{strdup} or @code{asprintf} to construct strings. @end deftypefun @comment wchar.h diff --git a/string/Makefile b/string/Makefile index ebe9354..0d1fb52 100644 --- a/string/Makefile +++ b/string/Makefile @@ -41,7 +41,7 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \ addsep replace) \ envz basename \ strcoll_l strxfrm_l string-inlines memrchr \ - xpg-strerror strerror_l + xpg-strerror strerror_l strlcpy strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \ stpcpy stpncpy strcat strchr strcmp strcpy strcspn \ @@ -54,7 +54,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \ tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \ bug-strtok1 $(addprefix test-,$(strop-tests)) \ bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \ - tst-strtok_r bug-strcoll2 + tst-strtok_r bug-strcoll2 tst-strlcpy xtests = tst-strcoll-overflow diff --git a/string/Versions b/string/Versions index 59bf35a..bd00ca1 100644 --- a/string/Versions +++ b/string/Versions @@ -80,4 +80,7 @@ libc { GLIBC_2.6 { strerror_l; } + GLIBC_2.23 { + strlcpy; + } } diff --git a/string/bits/string3.h b/string/bits/string3.h index 4d11aa6..9f28a73 100644 --- a/string/bits/string3.h +++ b/string/bits/string3.h @@ -40,6 +40,7 @@ __warndecl (__warn_memset_zero_len, # undef stpcpy # endif # ifdef __USE_MISC +# undef strlcpy # undef bcopy # undef bzero # endif @@ -155,3 +156,29 @@ __NTH (strncat (char *__restrict __dest, const char *__restrict __src, { return __builtin___strncat_chk (__dest, __src, __len, __bos (__dest)); } + +#ifdef __USE_MISC +__warndecl (__warn_strlcpy_size_zero, + "strlcpy used with a size argument of zero"); +__warndecl (__warn_strlcpy_size_large, + "strlcpy used with a size argument which is too large"); +extern size_t __strlcpy_chk (char *__dest, const char *__src, size_t __n, + size_t __destlen) __THROW; + +__fortify_function size_t +__NTH (strlcpy (char *__restrict __dest, const char *__restrict __src, + size_t __len)) +{ + if (__builtin_constant_p (__len == 0) && __len == 0) + { + __warn_strlcpy_size_zero (); + return 0; + } + if (__builtin_constant_p (__len > __bos (__dest)) && __len > __bos (__dest)) + __warn_strlcpy_size_large (); + if (__builtin_constant_p (__bos (__dest) == (size_t) -1) + && __bos (__dest) == (size_t) -1) + return strlcpy (__dest, __src, __len); + return __strlcpy_chk (__dest, __src, __len, __bos (__dest)); +} +#endif diff --git a/string/string.h b/string/string.h index 3ab7103..92a5d80 100644 --- a/string/string.h +++ b/string/string.h @@ -574,6 +574,13 @@ extern char *stpncpy (char *__restrict __dest, __THROW __nonnull ((1, 2)); #endif +#ifdef __USE_MISC +/* Copy at most N characters from SRC to DEST. */ +extern size_t strlcpy (char *__restrict __dest, + const char *__restrict __src, size_t __n) + __THROW __nonnull ((1, 2)); +#endif + #ifdef __USE_GNU /* Compare S1 and S2 as strings holding name & indices/version numbers. */ extern int strverscmp (const char *__s1, const char *__s2) diff --git a/string/strlcpy.c b/string/strlcpy.c new file mode 100644 index 0000000..3833a50 --- /dev/null +++ b/string/strlcpy.c @@ -0,0 +1,47 @@ +/* Copy a null-terminated string to a fixed-size buffer, with length checking. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> + +#undef strlcpy + +size_t +strlcpy (char *__restrict dest, const char *__restrict src, size_t size) +{ + size_t src_length = strlen (src); + + if (__glibc_unlikely (src_length >= size)) + { + if (size > 0) + { + /* Copy the leading portion of the string. The last + character is subsequently overwritten with the NUL + terminator, but the destination size is usually a + multiple of a small power of two, so writing it twice + should be more efficient than copying an odd number of + bytes. */ + memcpy (dest, src, size); + dest[size - 1] = '\0'; + } + } + else + /* Copy the string and its terminating NUL character. */ + memcpy (dest, src, src_length + 1); + return src_length; +} +libc_hidden_def (strlcpy) diff --git a/string/tst-strlcpy.c b/string/tst-strlcpy.c new file mode 100644 index 0000000..b97f591 --- /dev/null +++ b/string/tst-strlcpy.c @@ -0,0 +1,66 @@ +/* Test the strlcpy function. + Copyright (C) 2015 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#define CHECK(cond) \ + if (!(cond)) \ + { \ + printf ("%s:%d: FAIL\n", __FILE__, __LINE__); \ + exit (1); \ + } + +static int +do_test (void) +{ + struct { + char buf1[16]; + char buf2[16]; + } s; + + memset (&s, '@', sizeof (s)); + CHECK (strlcpy (s.buf1, "Hello!", 0) == 6); + CHECK (memcmp (&s, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", sizeof (s)) == 0); + + memset (&s, '@', sizeof (s)); + CHECK (strlcpy (s.buf1, "Hello!", sizeof (s.buf1)) == 6); + CHECK (memcmp (&s, "Hello!\0@@@@@@@@@@@@@@@@@@@@@@@@@", sizeof (s)) == 0); + + memset (&s, '@', sizeof (s)); + CHECK (strlcpy (s.buf1, "Hello, world!!!", sizeof (s.buf1)) == 15); + CHECK (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", + sizeof (s)) == 0); + + memset (&s, '@', sizeof (s)); + CHECK (strlcpy (s.buf1, "Hello, world!!!!", sizeof (s.buf1)) == 16); + CHECK (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", + sizeof (s)) == 0); + + memset (&s, '@', sizeof (s)); + CHECK (strlcpy (s.buf1, "Hello, world!!!!!!!!", sizeof (s.buf1)) == 20); + CHECK (memcmp (&s, "Hello, world!!!\0@@@@@@@@@@@@@@@@@@@@@@@@@", + sizeof (s)) == 0); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" + diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist index 561441e..9137c51 100644 --- a/sysdeps/arm/nacl/libc.abilist +++ b/sysdeps/arm/nacl/libc.abilist @@ -1834,3 +1834,6 @@ GLIBC_2.22 wprintf F GLIBC_2.22 write F GLIBC_2.22 writev F GLIBC_2.22 wscanf F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist index c1ba62c..62c6412 100644 --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist @@ -2081,3 +2081,6 @@ GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.18 _mcount F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist index 7d2d121..e5bff7e 100644 --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist @@ -1992,6 +1992,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist index a30b258..5e7f8e9 100644 --- a/sysdeps/unix/sysv/linux/arm/libc.abilist +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist @@ -82,6 +82,9 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 _Exit F GLIBC_2.4 _IO_2_1_stderr_ D 0xa0 diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist index 571548a..ff90320 100644 --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist @@ -1846,6 +1846,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist index 87abbbd..ecf1d72 100644 --- a/sysdeps/unix/sysv/linux/i386/libc.abilist +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist @@ -2004,6 +2004,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist index 1cbdffe..8039f68 100644 --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist @@ -1868,6 +1868,9 @@ GLIBC_2.2.6 __nanosleep F GLIBC_2.2.6 getunwind F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist index 061b5ee..8053211 100644 --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist @@ -83,6 +83,9 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.4 GLIBC_2.4 A GLIBC_2.4 _Exit F GLIBC_2.4 _IO_2_1_stderr_ D 0x98 diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist index 91be3d8..d3d9863 100644 --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist @@ -1960,6 +1960,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist index c1b1cad..6fe3aeb 100644 --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist @@ -2081,3 +2081,6 @@ GLIBC_2.18 xprt_register F GLIBC_2.18 xprt_unregister F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist index 3ef9b99..87de055 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist @@ -1935,6 +1935,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist index c44ee13..aed7e26 100644 --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist @@ -1933,6 +1933,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist index e8908e4..06d5c94 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist @@ -1931,6 +1931,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist index c6d1da2..e06e184 100644 --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist @@ -1926,6 +1926,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist index 703979a..c837ec4 100644 --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist @@ -2122,3 +2122,6 @@ GLIBC_2.21 xprt_register F GLIBC_2.21 xprt_unregister F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist index 90ca484..866c0c5 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist @@ -1964,6 +1964,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist index a5ecc76..2b647f7 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist @@ -1969,6 +1969,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist index c6bea69..b0359b2 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist @@ -2169,3 +2169,6 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist index 21e736b..df9a5f5 100644 --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist @@ -83,6 +83,9 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 _Exit F GLIBC_2.3 _IO_2_1_stderr_ D 0xe0 diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist index d6c037b..12528d0 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist @@ -1964,6 +1964,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist index 02422da..99d63b4 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist @@ -1865,6 +1865,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist index 5accb42..5d7baaa 100644 --- a/sysdeps/unix/sysv/linux/sh/libc.abilist +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist @@ -1850,6 +1850,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist index 0ecba65..eda8cc2 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist @@ -1956,6 +1956,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist index ce45412..9c72aaf 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist @@ -1894,6 +1894,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist index 63441e9..50bbb2d 100644 --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist index 212e4d5..51c87cd 100644 --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist index 63441e9..50bbb2d 100644 --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist index afb29dc..60e85dc 100644 --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist @@ -1845,6 +1845,9 @@ GLIBC_2.2.6 GLIBC_2.2.6 A GLIBC_2.2.6 __nanosleep F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F GLIBC_2.3 GLIBC_2.3 A GLIBC_2.3 __ctype_b_loc F GLIBC_2.3 __ctype_tolower_loc F diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist index 7ac7104..386d4b3 100644 --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist @@ -2088,3 +2088,6 @@ GLIBC_2.18 GLIBC_2.18 A GLIBC_2.18 __cxa_thread_atexit_impl F GLIBC_2.22 GLIBC_2.22 A GLIBC_2.22 fmemopen F +GLIBC_2.23 GLIBC_2.23 A +GLIBC_2.23 __strlcpy_chk F +GLIBC_2.23 strlcpy F