Collin Funk wrote:
> FreeBSD 15.0 was released today.

In a testdir, I see a test failure:

FAIL: test-u8-strncpy
=====================

FAIL test-u8-strncpy (exit status: 139)

u8_strncpy() merely calls strncpy(). Therefore, when u8_strncpy has a bug,
it must be a bug in strncpy.

The attached patches
  1) lift the unit test from u8_strncpy to strncpy, so that the unit test
     of strncpy fails as well,
  2) un-obsoletes the 'strncpy' module and adds a workaround,
  3) makes sure this workaround gets used where needed in Gnulib.

Packages that call strncpy() still need to import this module manually.

Collin, again, you might want to report it to the FreeBSD people.
The reproducer is contained in m4/strncpy.m4.
The buggy commit is FreeBSD commit e19d46c808267f53455e96a28ff7654211523d2c.


2025-12-02  Bruno Haible  <[email protected]>

        Make use of the strncpy module.
        * modules/unistr/u8-strncpy (Depends-on): Add strncpy.
        * modules/crypto/rijndael (Depends-on): Likewise.
        * modules/gethostname (Depends-on): Likewise.
        * modules/localename-unsafe (Depends-on): Likewise.
        * modules/localename-unsafe-limited (Depends-on): Likewise.
        * modules/regex (Depends-on): Likewise.
        * modules/setlocale-fixes (Depends-on): Likewise.

2025-12-02  Bruno Haible  <[email protected]>

        strncpy: Add workaround for FreeBSD 15.0/x86_64.
        * lib/string.in.h (strncpy): New declaration.
        * lib/strncpy.c: New file, based on lib/wcsncpy-impl.h.
        * m4/strncpy.m4: New file, based on m4/strncat.m4.
        * m4/string_h.m4 (gl_STRING_H): Test whether strncpy is declared.
        (gl_STRING_H_REQUIRE_DEFAULTS): Initialize GNULIB_STRNCPY.
        (gl_STRING_H_DEFAULTS): Initialize REPLACE_STRNCPY.
        * modules/string-h (Makefile.am): Substitute GNULIB_STRNCPY,
        REPLACE_STRNCPY.
        * modules/strncpy (Status, Notice): Remove.
        (Files): Add lib/strncpy.c, m4/strncpy.m4, m4/mmap-anon.m4.
        (configure.ac): Invoke gl_FUNC_STRNCPY. Arrange to define
        GNULIB_STRNCPY. Add GL_COND_OBJ_STRNCPY conditional.
        (Makefile.am): Arrange to conditionally compile strncpy.c.
        * tests/test-string-h-c++.cc: Check signature of strncpy.
        * doc/posix-functions/strncpy.texi: Mention the FreeBSD bug.

2025-12-02  Bruno Haible  <[email protected]>

        strncpy tests: Enhance test.
        * tests/test-strncpy.c: Include zerosize-ptr.h.
        (MAGIC): New macro.
        (check-single, check): New functions, based on
        tests/unistr/test-strncpy.h.
        (main): Invoke check().
        * modules/strncpy-tests (Files): Add tests/zerosize-ptr.h,
        m4/mmap-anon.m4.
        (Depends-on): Add extensions.
        (configure.ac): Invoke gl_FUNC_MMAP_ANON. Check for <sys/mman.h> and
        mprotect.

From da470282b397fcb92b8599788ef1482a228e9cc6 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Tue, 2 Dec 2025 21:44:08 +0100
Subject: [PATCH 1/3] strncpy tests: Enhance test.

* tests/test-strncpy.c: Include zerosize-ptr.h.
(MAGIC): New macro.
(check-single, check): New functions, based on
tests/unistr/test-strncpy.h.
(main): Invoke check().
* modules/strncpy-tests (Files): Add tests/zerosize-ptr.h,
m4/mmap-anon.m4.
(Depends-on): Add extensions.
(configure.ac): Invoke gl_FUNC_MMAP_ANON. Check for <sys/mman.h> and
mprotect.
---
 ChangeLog             | 14 +++++++++
 modules/strncpy-tests |  6 ++++
 tests/test-strncpy.c  | 73 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index 06a03d3c3a..5c1dbae465 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2025-12-02  Bruno Haible  <[email protected]>
+
+	strncpy tests: Enhance test.
+	* tests/test-strncpy.c: Include zerosize-ptr.h.
+	(MAGIC): New macro.
+	(check-single, check): New functions, based on
+	tests/unistr/test-strncpy.h.
+	(main): Invoke check().
+	* modules/strncpy-tests (Files): Add tests/zerosize-ptr.h,
+	m4/mmap-anon.m4.
+	(Depends-on): Add extensions.
+	(configure.ac): Invoke gl_FUNC_MMAP_ANON. Check for <sys/mman.h> and
+	mprotect.
+
 2025-12-02  Bruno Haible  <[email protected]>
 
 	realloc-posix: Add workaround for FreeBSD 15.0.
diff --git a/modules/strncpy-tests b/modules/strncpy-tests
index c21d2ac3fd..4a88128612 100644
--- a/modules/strncpy-tests
+++ b/modules/strncpy-tests
@@ -1,10 +1,16 @@
 Files:
 tests/test-strncpy.c
+tests/zerosize-ptr.h
 tests/macros.h
+m4/mmap-anon.m4
 
 Depends-on:
+extensions
 
 configure.ac:
+gl_FUNC_MMAP_ANON
+AC_CHECK_HEADERS_ONCE([sys/mman.h])
+AC_CHECK_FUNCS_ONCE([mprotect])
 
 Makefile.am:
 TESTS += test-strncpy
diff --git a/tests/test-strncpy.c b/tests/test-strncpy.c
index 165dd05b9c..d3862444cc 100644
--- a/tests/test-strncpy.c
+++ b/tests/test-strncpy.c
@@ -1,5 +1,5 @@
 /* Test of strncpy() function.
-   Copyright (C) 2024-2025 Free Software Foundation, Inc.
+   Copyright (C) 2010-2025 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@
 
 #include <stddef.h>
 
+#include "zerosize-ptr.h"
 #include "macros.h"
 
 /* Test the library, not the compiler+library.  */
@@ -34,9 +35,79 @@ static char *(*volatile volatile_strncpy) (char *, char const *, size_t)
 #undef strncpy
 #define strncpy volatile_strncpy
 
+#define MAGIC (char)0xBA
+
+static void
+check_single (const char *input, size_t length, size_t n)
+{
+  char *dest;
+  char *result;
+
+  dest = (char *) malloc (1 + n + 1);
+  ASSERT (dest != NULL);
+
+  for (size_t i = 0; i < 1 + n + 1; i++)
+    dest[i] = MAGIC;
+
+  result = strncpy (dest + 1, input, n);
+  ASSERT (result == dest + 1);
+
+  ASSERT (dest[0] == MAGIC);
+  {
+    size_t i;
+    for (i = 0; i < (n <= length ? n : length + 1); i++)
+      ASSERT (dest[1 + i] == input[i]);
+    for (; i < n; i++)
+      ASSERT (dest[1 + i] == 0);
+  }
+  ASSERT (dest[1 + n] == MAGIC);
+
+  free (dest);
+}
+
+static void
+check (const char *input, size_t input_length)
+{
+  size_t length;
+
+  ASSERT (input_length > 0);
+  ASSERT (input[input_length - 1] == 0);
+  length = input_length - 1; /* = strlen (input) */
+
+  for (size_t n = 0; n <= 2 * length + 2; n++)
+    check_single (input, length, n);
+
+  /* Check that strncpy (D, S, N) does not look at more than
+     MIN (strlen (S) + 1, N) units.  */
+  {
+    char *page_boundary = (char *) zerosize_ptr ();
+
+    if (page_boundary != NULL)
+      {
+        for (size_t n = 0; n <= 2 * length + 2; n++)
+          {
+            size_t n_to_copy = (n <= length ? n : length + 1);
+            char *copy;
+
+            copy = (char *) page_boundary - n_to_copy;
+            for (size_t i = 0; i < n_to_copy; i++)
+              copy[i] = input[i];
+
+            check_single (copy, length, n);
+          }
+      }
+  }
+}
+
 int
 main (void)
 {
+  /* Simple string.  */
+  { /* "Gr???? Gott." */
+    static const char input[] = "Gr\303\274\303\237 Gott.";
+    check (input, SIZEOF (input));
+  }
+
   /* Test zero-length operations on NULL pointers, allowed by
      <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3322.pdf>.  */
 
-- 
2.51.0

>From 4672014affaada90877a1d6ff20d42d88ccaf3a9 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Tue, 2 Dec 2025 22:14:13 +0100
Subject: [PATCH 2/3] strncpy: Add workaround for FreeBSD 15.0/x86_64.

* lib/string.in.h (strncpy): New declaration.
* lib/strncpy.c: New file, based on lib/wcsncpy-impl.h.
* m4/strncpy.m4: New file, based on m4/strncat.m4.
* m4/string_h.m4 (gl_STRING_H): Test whether strncpy is declared.
(gl_STRING_H_REQUIRE_DEFAULTS): Initialize GNULIB_STRNCPY.
(gl_STRING_H_DEFAULTS): Initialize REPLACE_STRNCPY.
* modules/string-h (Makefile.am): Substitute GNULIB_STRNCPY,
REPLACE_STRNCPY.
* modules/strncpy (Status, Notice): Remove.
(Files): Add lib/strncpy.c, m4/strncpy.m4, m4/mmap-anon.m4.
(configure.ac): Invoke gl_FUNC_STRNCPY. Arrange to define
GNULIB_STRNCPY. Add GL_COND_OBJ_STRNCPY conditional.
(Makefile.am): Arrange to conditionally compile strncpy.c.
* tests/test-string-h-c++.cc: Check signature of strncpy.
* doc/posix-functions/strncpy.texi: Mention the FreeBSD bug.
---
 ChangeLog                        | 19 +++++++
 doc/posix-functions/strncpy.texi |  8 +++
 lib/string.in.h                  | 29 ++++++++++
 lib/strncpy.c                    | 38 +++++++++++++
 m4/string_h.m4                   |  6 +-
 m4/strncpy.m4                    | 94 ++++++++++++++++++++++++++++++++
 modules/string-h                 |  2 +
 modules/strncpy                  | 18 ++++--
 tests/test-string-h-c++.cc       |  5 ++
 9 files changed, 211 insertions(+), 8 deletions(-)
 create mode 100644 lib/strncpy.c
 create mode 100644 m4/strncpy.m4

diff --git a/ChangeLog b/ChangeLog
index 5c1dbae465..6db54531a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2025-12-02  Bruno Haible  <[email protected]>
+
+	strncpy: Add workaround for FreeBSD 15.0/x86_64.
+	* lib/string.in.h (strncpy): New declaration.
+	* lib/strncpy.c: New file, based on lib/wcsncpy-impl.h.
+	* m4/strncpy.m4: New file, based on m4/strncat.m4.
+	* m4/string_h.m4 (gl_STRING_H): Test whether strncpy is declared.
+	(gl_STRING_H_REQUIRE_DEFAULTS): Initialize GNULIB_STRNCPY.
+	(gl_STRING_H_DEFAULTS): Initialize REPLACE_STRNCPY.
+	* modules/string-h (Makefile.am): Substitute GNULIB_STRNCPY,
+	REPLACE_STRNCPY.
+	* modules/strncpy (Status, Notice): Remove.
+	(Files): Add lib/strncpy.c, m4/strncpy.m4, m4/mmap-anon.m4.
+	(configure.ac): Invoke gl_FUNC_STRNCPY. Arrange to define
+	GNULIB_STRNCPY. Add GL_COND_OBJ_STRNCPY conditional.
+	(Makefile.am): Arrange to conditionally compile strncpy.c.
+	* tests/test-string-h-c++.cc: Check signature of strncpy.
+	* doc/posix-functions/strncpy.texi: Mention the FreeBSD bug.
+
 2025-12-02  Bruno Haible  <[email protected]>
 
 	strncpy tests: Enhance test.
diff --git a/doc/posix-functions/strncpy.texi b/doc/posix-functions/strncpy.texi
index 8dd33de80e..6ccb28b25e 100644
--- a/doc/posix-functions/strncpy.texi
+++ b/doc/posix-functions/strncpy.texi
@@ -16,6 +16,14 @@
 macOS 10.8.
 @end itemize
 
+Portability problems fixed by Gnulib module @code{strncpy}:
+@itemize
+@item
+This function looks are more bytes of the source string than allowed
+on some platforms:
+FreeBSD 15.0/x86_64.
+@end itemize
+
 Portability problems not fixed by Gnulib:
 @itemize
 @end itemize
diff --git a/lib/string.in.h b/lib/string.in.h
index a323b1cd6d..f316878b4c 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -840,6 +840,35 @@ _GL_WARN_ON_USE (strncat, "strncat is unportable - "
 # endif
 #endif
 
+/* Copy no more than N bytes of SRC to DST, returning DST.  */
+#if @GNULIB_STRNCPY@
+# if @REPLACE_STRNCPY@
+#  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#   undef strncpy
+#   define strncpy rpl_strncpy
+#  endif
+_GL_FUNCDECL_RPL (strncpy, char *,
+                  (char *restrict __dst, char const *restrict __src,
+                   size_t __n),
+                  _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (strncpy, char *,
+                  (char *restrict __dst, char const *restrict __src,
+                   size_t __n));
+# else
+_GL_CXXALIAS_SYS (strncpy, char *,
+                  (char *restrict __dst, char const *restrict __src,
+                   size_t __n));
+# endif
+# if __GLIBC__ >= 2
+_GL_CXXALIASWARN (strncpy);
+# endif
+#elif defined GNULIB_POSIXCHECK
+# if HAVE_RAW_DECL_STRNCPY
+_GL_WARN_ON_USE (strncpy, "strncpy is unportable - "
+                 "use gnulib module strncpy for portability");
+# endif
+#endif
+
 /* Return a newly allocated copy of at most N bytes of STRING.  */
 #if @GNULIB_STRNDUP@
 # if @REPLACE_STRNDUP@
diff --git a/lib/strncpy.c b/lib/strncpy.c
new file mode 100644
index 0000000000..1b6800469a
--- /dev/null
+++ b/lib/strncpy.c
@@ -0,0 +1,38 @@
+/* Copy a size-bounded string.
+   Copyright (C) 1999, 2011-2025 Free Software Foundation, Inc.
+
+   This file 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 3 of the
+   License, or (at your option) any later version.
+
+   This file 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 this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <[email protected]>, 1999.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <string.h>
+
+char *
+strncpy (char *dest, const char *src, size_t n)
+{
+  char *destptr = dest;
+
+  for (; n > 0 && (*destptr = *src) != '\0'; src++, destptr++, n--)
+    ;
+
+  /* This behavior is rarely useful, but it is specified by the ISO C
+     standard.  */
+  for (; n > 0; n--)
+    *destptr++ = '\0';
+
+  return dest;
+}
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index b5324e3a37..860440123a 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -1,5 +1,5 @@
 # string_h.m4
-# serial 45
+# serial 46
 dnl Copyright (C) 2007-2025 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -24,7 +24,7 @@ AC_DEFUN_ONCE([gl_STRING_H]
     ]],
     [explicit_bzero ffsl ffsll memmem mempcpy memrchr memset_explicit
      rawmemchr stpcpy stpncpy strchrnul
-     strdup strncat strndup strnlen strpbrk strsep strcasestr strtok_r
+     strdup strncat strncpy strndup strnlen strpbrk strsep strcasestr strtok_r
      strerror_l strerror_r strerrorname_np
      sigabbrev_np sigdescr_np strsignal strverscmp])
 
@@ -65,6 +65,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRDUP])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRINGEQ])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNCAT])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNCPY])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNDUP])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRNLEN])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRPBRK])
@@ -149,6 +150,7 @@ AC_DEFUN([gl_STRING_H_DEFAULTS]
   REPLACE_STRCHRNUL=0;          AC_SUBST([REPLACE_STRCHRNUL])
   REPLACE_STRDUP=0;             AC_SUBST([REPLACE_STRDUP])
   REPLACE_STRNCAT=0;            AC_SUBST([REPLACE_STRNCAT])
+  REPLACE_STRNCPY=0;            AC_SUBST([REPLACE_STRNCPY])
   REPLACE_STRNDUP=0;            AC_SUBST([REPLACE_STRNDUP])
   REPLACE_STRNLEN=0;            AC_SUBST([REPLACE_STRNLEN])
   REPLACE_STRSTR=0;             AC_SUBST([REPLACE_STRSTR])
diff --git a/m4/strncpy.m4 b/m4/strncpy.m4
new file mode 100644
index 0000000000..5787617133
--- /dev/null
+++ b/m4/strncpy.m4
@@ -0,0 +1,94 @@
+# strncpy.m4
+# serial 1
+dnl Copyright (C) 2002-2004, 2009-2025 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl This file is offered as-is, without any warranty.
+
+AC_DEFUN_ONCE([gl_FUNC_STRNCPY],
+[
+  AC_REQUIRE([gl_STRING_H_DEFAULTS])
+  AC_REQUIRE([AC_PROG_CC])
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  dnl Check for prerequisites for memory fence checks.
+  gl_FUNC_MMAP_ANON
+  AC_CHECK_HEADERS_ONCE([sys/mman.h])
+  AC_CHECK_FUNCS_ONCE([mprotect])
+
+  dnl Detect bug in FreeBSD 15.0 on x86_64:
+  dnl strncpy should not dereference more than n bytes, but always dereferences
+  dnl n+1 bytes if the first n bytes don't contain a NUL byte.
+  dnl Assume that strncpy works on platforms that lack mprotect.
+  AC_CACHE_CHECK([whether strncpy works], [gl_cv_func_strncpy_works],
+    [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <string.h>
+#if HAVE_SYS_MMAN_H
+# include <fcntl.h>
+# include <unistd.h>
+# include <sys/types.h>
+# include <sys/mman.h>
+#endif
+]GL_MDA_DEFINES],
+[[
+  char *fence = NULL;
+#if HAVE_SYS_MMAN_H && HAVE_MPROTECT
+  {
+    long int pagesize = sysconf (_SC_PAGESIZE);
+    char *two_pages =
+      (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
+                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+    if (two_pages != (char *)(-1)
+        && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
+      fence = two_pages + pagesize;
+  }
+#endif
+  if (fence)
+    {
+      char dest[8];
+
+      dest[0] = 'a';
+      dest[1] = 'b';
+      dest[2] = 'c';
+      dest[3] = 'd';
+      dest[4] = 'e';
+      dest[5] = 'f';
+      dest[6] = 'g';
+
+      *(fence - 3) = '7';
+      *(fence - 2) = '2';
+      *(fence - 1) = '9';
+
+      if (strncpy (dest + 1, fence - 3, 3) != dest + 1)
+        return 1;
+      if (dest[0] != 'a')
+        return 2;
+      if (dest[1] != '7' || dest[2] != '2' || dest[3] != '9')
+        return 3;
+      if (dest[4] != 'e')
+        return 4;
+    }
+  return 0;
+]])], [gl_cv_func_strncpy_works=yes], [gl_cv_func_strncpy_works=no],
+       [
+        case "$host_os" in
+                                 # Guess no on FreeBSD.
+          freebsd* | dragonfly*) gl_cv_func_strncpy_works="guessing no" ;;
+                                 # Guess yes on native Windows.
+          mingw* | windows*)     gl_cv_func_strncpy_works="guessing yes" ;;
+                                 # Guess yes otherwise.
+          *)                     gl_cv_func_strncpy_works="guessing yes" ;;
+        esac
+       ])
+    ])
+  case "$gl_cv_func_strncpy_works" in
+    *yes) ;;
+    *) REPLACE_STRNCPY=1 ;;
+  esac
+])
+
+# Prerequisites of lib/strncpy.c.
+AC_DEFUN([gl_PREREQ_STRNCPY], [
+  :
+])
diff --git a/modules/string-h b/modules/string-h
index 90ed663ae8..3e69040ea4 100644
--- a/modules/string-h
+++ b/modules/string-h
@@ -65,6 +65,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's/@''GNULIB_STRDUP''@/$(GNULIB_STRDUP)/g' \
 	      -e 's/@''GNULIB_STRINGEQ''@/$(GNULIB_STRINGEQ)/g' \
 	      -e 's/@''GNULIB_STRNCAT''@/$(GNULIB_STRNCAT)/g' \
+	      -e 's/@''GNULIB_STRNCPY''@/$(GNULIB_STRNCPY)/g' \
 	      -e 's/@''GNULIB_STRNDUP''@/$(GNULIB_STRNDUP)/g' \
 	      -e 's/@''GNULIB_STRNLEN''@/$(GNULIB_STRNLEN)/g' \
 	      -e 's/@''GNULIB_STRPBRK''@/$(GNULIB_STRPBRK)/g' \
@@ -126,6 +127,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's|@''REPLACE_STRCHRNUL''@|$(REPLACE_STRCHRNUL)|g' \
 	      -e 's|@''REPLACE_STRDUP''@|$(REPLACE_STRDUP)|g' \
 	      -e 's|@''REPLACE_STRNCAT''@|$(REPLACE_STRNCAT)|g' \
+	      -e 's|@''REPLACE_STRNCPY''@|$(REPLACE_STRNCPY)|g' \
 	      -e 's|@''REPLACE_STRNDUP''@|$(REPLACE_STRNDUP)|g' \
 	      -e 's|@''REPLACE_STRNLEN''@|$(REPLACE_STRNLEN)|g' \
 	      -e 's|@''REPLACE_STRSTR''@|$(REPLACE_STRSTR)|g' \
diff --git a/modules/strncpy b/modules/strncpy
index ac1188605b..79dbdcaf4f 100644
--- a/modules/strncpy
+++ b/modules/strncpy
@@ -1,20 +1,26 @@
 Description:
 Copy the initial part of a string.
 
-Status:
-obsolete
-
-Notice:
-This module is obsolete.
-
 Files:
+lib/strncpy.c
+m4/strncpy.m4
+m4/mmap-anon.m4
 
 Depends-on:
 string-h
 
 configure.ac:
+gl_FUNC_STRNCPY
+gl_CONDITIONAL([GL_COND_OBJ_STRNCPY], [test $REPLACE_STRNCPY = 1])
+AM_COND_IF([GL_COND_OBJ_STRNCPY], [
+  gl_PREREQ_STRNCPY
+])
+gl_STRING_MODULE_INDICATOR([strncpy])
 
 Makefile.am:
+if GL_COND_OBJ_STRNCPY
+lib_SOURCES += strncpy.c
+endif
 
 Include:
 <string.h>
diff --git a/tests/test-string-h-c++.cc b/tests/test-string-h-c++.cc
index e5b45653fc..ff48c02fc8 100644
--- a/tests/test-string-h-c++.cc
+++ b/tests/test-string-h-c++.cc
@@ -81,6 +81,11 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::strncat, char *,
                  (char *, const char *, size_t));
 #endif
 
+#if GNULIB_TEST_STRNCPY
+SIGNATURE_CHECK (GNULIB_NAMESPACE::strncpy, char *,
+                 (char *, const char *, size_t));
+#endif
+
 #if GNULIB_TEST_STRNDUP
 SIGNATURE_CHECK (GNULIB_NAMESPACE::strndup, char *, (char const *, size_t));
 #endif
-- 
2.51.0

>From c2e279b2b130c43e2f6bf34503db6594f61b2705 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Tue, 2 Dec 2025 22:18:52 +0100
Subject: [PATCH 3/3] Make use of the strncpy module.

* modules/unistr/u8-strncpy (Depends-on): Add strncpy.
* modules/crypto/rijndael (Depends-on): Likewise.
* modules/gethostname (Depends-on): Likewise.
* modules/localename-unsafe (Depends-on): Likewise.
* modules/localename-unsafe-limited (Depends-on): Likewise.
* modules/regex (Depends-on): Likewise.
* modules/setlocale-fixes (Depends-on): Likewise.
---
 ChangeLog                         | 11 +++++++++++
 modules/crypto/rijndael           |  1 +
 modules/gethostname               |  1 +
 modules/localename-unsafe         |  1 +
 modules/localename-unsafe-limited |  1 +
 modules/regex                     |  1 +
 modules/setlocale-fixes           |  1 +
 modules/unistr/u8-strncpy         |  1 +
 8 files changed, 18 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 6db54531a3..1e727e6ba3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2025-12-02  Bruno Haible  <[email protected]>
+
+	Make use of the strncpy module.
+	* modules/unistr/u8-strncpy (Depends-on): Add strncpy.
+	* modules/crypto/rijndael (Depends-on): Likewise.
+	* modules/gethostname (Depends-on): Likewise.
+	* modules/localename-unsafe (Depends-on): Likewise.
+	* modules/localename-unsafe-limited (Depends-on): Likewise.
+	* modules/regex (Depends-on): Likewise.
+	* modules/setlocale-fixes (Depends-on): Likewise.
+
 2025-12-02  Bruno Haible  <[email protected]>
 
 	strncpy: Add workaround for FreeBSD 15.0/x86_64.
diff --git a/modules/crypto/rijndael b/modules/crypto/rijndael
index 2fcc3d3d87..b1bcb680dd 100644
--- a/modules/crypto/rijndael
+++ b/modules/crypto/rijndael
@@ -9,6 +9,7 @@ lib/rijndael-api-fst.h
 
 Depends-on:
 stdint-h
+strncpy
 
 configure.ac:
 AC_REQUIRE([AC_C_RESTRICT])
diff --git a/modules/gethostname b/modules/gethostname
index 0e4cc30f14..093d13a132 100644
--- a/modules/gethostname
+++ b/modules/gethostname
@@ -12,6 +12,7 @@ sys_socket-h    [test $HAVE_GETHOSTNAME = 0]
 errno-h         [test $HAVE_GETHOSTNAME = 0]
 sockets         [test $HAVE_GETHOSTNAME = 0]
 msvc-nothrow    [test $HAVE_GETHOSTNAME = 0]
+strncpy         [test $HAVE_GETHOSTNAME = 0]
 
 configure.ac:
 gl_FUNC_GETHOSTNAME
diff --git a/modules/localename-unsafe b/modules/localename-unsafe
index 37d225a74b..5785dd4462 100644
--- a/modules/localename-unsafe
+++ b/modules/localename-unsafe
@@ -18,6 +18,7 @@ extensions
 locale-h
 strdup
 stringeq
+strncpy
 windows-mutex
 getlocalename_l-unsafe
 setlocale-null-unlocked
diff --git a/modules/localename-unsafe-limited b/modules/localename-unsafe-limited
index f1b9f12205..1593ce2784 100644
--- a/modules/localename-unsafe-limited
+++ b/modules/localename-unsafe-limited
@@ -17,6 +17,7 @@ localename-environ
 extensions
 locale-h
 strdup
+strncpy
 windows-mutex
 getlocalename_l-unsafe-limited
 setlocale-null-unlocked
diff --git a/modules/regex b/modules/regex
index 75e897edde..d043dc1e7a 100644
--- a/modules/regex
+++ b/modules/regex
@@ -40,6 +40,7 @@ nl_langinfo             [test $ac_use_included_regex = yes]
 bool                    [test $ac_use_included_regex = yes]
 stdckdint-h             [test $ac_use_included_regex = yes]
 stdint-h                [test $ac_use_included_regex = yes]
+strncpy                 [test $ac_use_included_regex = yes]
 verify                  [test $ac_use_included_regex = yes]
 wchar-h                 [test $ac_use_included_regex = yes]
 wcrtomb                 [test $ac_use_included_regex = yes]
diff --git a/modules/setlocale-fixes b/modules/setlocale-fixes
index 7ab3bd821c..9b1f00572a 100644
--- a/modules/setlocale-fixes
+++ b/modules/setlocale-fixes
@@ -7,6 +7,7 @@ lib/setlocale-fixes.c
 
 Depends-on:
 stringeq
+strncpy
 
 configure.ac:
 AC_REQUIRE([AC_CANONICAL_HOST])
diff --git a/modules/unistr/u8-strncpy b/modules/unistr/u8-strncpy
index 1870e03790..a600059691 100644
--- a/modules/unistr/u8-strncpy
+++ b/modules/unistr/u8-strncpy
@@ -6,6 +6,7 @@ lib/unistr/u8-strncpy.c
 
 Depends-on:
 unistr/base
+strncpy
 
 configure.ac:
 gl_LIBUNISTRING_MODULE([0.9], [unistr/u8-strncpy])
-- 
2.51.0

Reply via email to