[Bug 291359] x86_64 strncpy/stpncpy reads extra bytes from the source string.

[email protected] Wed, 03 Dec 2025 02:47:38 +0000
Newsgroups gmane.os.freebsd.devel.standards
Message-ID <[email protected]/bugzilla/>
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=291359

            Bug ID: 291359
           Summary: x86_64 strncpy/stpncpy reads extra bytes from the
                    source string.
           Product: Base System
           Version: 15.0-RELEASE
          Hardware: amd64
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: standards
          Assignee: [email protected]
          Reporter: [email protected]

Note that this bug should be filed under the amd64 component. However, the
bugzilla seems bugged and does not show the option when filing a bug.

Using this test program to map two pages and then make the second inaccessible,
we can see the strncpy and stpncpy reads bytes that it shouldn't:

```
$ cat main.c 
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#ifndef STRNCPY
# define STRNCPY strncpy
#endif
int
main (void)
{
  char *fence = NULL;
  long int pagesize = sysconf (_SC_PAGESIZE);
  /* Map two pages.  */
  char *two_pages =
    (char *) mmap (NULL, 2 * pagesize, PROT_READ | PROT_WRITE,
                   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  /* Make the second page inaccessible.  */
  if (two_pages != (char *)(-1)
      && mprotect (two_pages + pagesize, pagesize, PROT_NONE) == 0)
    fence = two_pages + pagesize;
  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;
}
$ cc main.c && ./a.out 
Segmentation fault         (core dumped) ./a.out
$ cc -DSTRNCPY=stpncpy main.c && ./a.out 
Segmentation fault         (core dumped) ./a.out
$ gdb ./a.out ./a.out.core
[...]
Reading symbols from ./a.out...
[New LWP 100560]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
Invalid permissions for mapped object.
#0  ?? () at /usr/src/lib/libc/amd64/string/stpncpy.S:230 from /lib/libc.so.7
230             movdqa          16(%rsi), %xmm0         # load second chunk of
input
```

Originally found in Gnulib and reported by Bruno Haible here:
https://lists.gnu.org/archive/html/bug-gnulib/2025-12/msg00023.html

-- 
You are receiving this mail because:
You are the assignee for the bug.