Bug#1135176: bookworm-pu: package glibc/2.36-9+deb12u14

Aurelien Jarno <[email protected]> Tue, 28 Apr 2026 21:30:18 +0200
Newsgroups gmane.linux.debian.devel.glibc
Message-ID <177740461834.1299934.4366026286898768756.reportbug__25267.7155238175$1777404844$gmane$org@ohm.local>
Package: release.debian.org
Severity: normal
Tags: bookworm
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:glibc
User: [email protected]
Usertags: pu

[ Reason ]
The upstream stable branch received many fixes since the latest bookworm
point release, and this update pulls them into the debian package. This
includes most notably 6 security fixes.

[ Impact ]
In case the update isn't approved, systems will be left with a few
issues, including 6 security ones, and the differences with upstream
will increase.

[ Tests ]
Most of the changes come with additional upstream tests, and one
additional test has been enabled.

[ Risks ]
I believe the risks are low, as a significant part of the changes are
already in trixie since the last point release. All the other changes
are in testing for more than 3 weeks, with the exception of the fix for
CVE-2026-4046 which entered testing only a couple of days ago. 

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
The changes are summarized in the changelog, let me give you a few extra
details for some of them:

 - Fix a performance bottleneck with the Address Sanitizer (ASAN) on 32-bit
   arm.

This is https://sourceware.org/bugzilla/show_bug.cgi?id=31405 upstream

 - Fix _dl_find_object when ld.so has LOAD segment gaps, causing wrong
   backtrace unwinding. This affects at least arm64.

This is https://sourceware.org/bugzilla/show_bug.cgi?id=31943 upstream

 - Fix typo in wmemset ifunc selector that caused AVX2/AVX512 paths to be
   skipped.

This is https://sourceware.org/bugzilla/show_bug.cgi?id=33542 upstream

 - Fix POWER optimized rawmemchr function on ppc64el.

This is https://sourceware.org/bugzilla/show_bug.cgi?id=33091 upstream

 - Optimize trylock for high cache contention workloads.

This is https://sourceware.org/bugzilla/show_bug.cgi?id=33704 upstream

 - Fix a typo preventing new tst-wordexp-reuse-mem to run

There was a typo in the makefile, causing the test to be ignored. This
just fixes that.

 - Fix random failure of tst-link-map-contiguous-ldso.

This test failure appears randomly, but has significantly more chances
to happen on a 16KiB page size kernel. This is the case for instance on
the 16k kernel we ship on arm64.

 - Add GLIBC_ABI_DT_X86_64_PLT symbol version on amd64.
 * d/p/amd64/local-revert-x86-64-add-GLIBC_ABI_DT_X86_64_PLT-version.diff:
 revert addition of the GLIBC_ABI_DT_X86_64_PLT symbol version used as ABI
 flag, as the dpkg-shlibdeps version in bookworm is not able to handle it
 (see #1122107).

This is the tricky part of the of this new bookworm-pu version. A bug in
the R_X86_64_GLOB_DAT and R_X86_64_JUMP_SLOT relocation (emitted when
using -z mark-plt) has been fixed in 2.36 (so already included in
bookworm). The GLIBC_ABI_DT_X86_64_PLT symbol version is therefore
emitted by binutils to ensure that binaries built with the fixed ABI are
only executed with a glibc that has the fix. This makes possible to
backport the fix to older glibc version instead of requiring a newer
glibc.

However the dpkg-shlibdeps version in bookworm is not able to handle
symbol versions not associated with any symbol (see #1122107). Therefore
the chosen approach is to just revert the symbol version addition (see
below). I do not expect the dpkg-shlibdeps bug to be fixed in bookworm
given it starts to be old, but users needing a binary compatibility with
other distribution can upgrade.

Note that that the same approach that was done in 2.41-12+deb13u2 in the
13.4 point release (just extended to more flags).

[ Other info ]
There are still a few pending CVEs to be fixed, but no visibility when
they'll be fixed, and I believe that it's better to have an upload not
too late before the point release.
glibc_2.36-9+deb12u14.debdiff (text/plain, 76.2 KB)
diff --git a/debian/changelog b/debian/changelog
index 87be104d..88dc4614 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,38 @@
+glibc (2.36-9+deb12u14) bookworm; urgency=medium
+
+  * debian/patches/git-updates.diff: update from upstream stable branch:
+    - Fix a performance bottleneck with the Address Sanitizer (ASAN) on 32-bit
+      arm.
+    - Fix _dl_find_object when ld.so has LOAD segment gaps, causing wrong
+      backtrace unwinding. This affects at least arm64.
+    - Add GLIBC_ABI_DT_X86_64_PLT symbol version on amd64.
+    - Fix typo in wmemset ifunc selector that caused AVX2/AVX512 paths to be
+      skipped.
+    - Fix POWER optimized rawmemchr function on ppc64el.
+    - Optimize trylock for high cache contention workloads.
+    - Fix and integer overflow in _int_memalign leading to heap corruption
+      (CVE-2026-0861).  Closes: #1125678.
+    - Fix stack contents leak in getnetbyaddr (CVE-2026-0915).  Closes:
+      #1125748.
+    - Fix bug in wordexp, which could return uninitialized memory when using
+      WRDE_REUSE together with WRDE_APPEND (CVE-2025-15281).  Closes: #1126266.
+    - Fix invalid pointer arithmetic in ANSI_X3.110 iconv module
+    - Fix a typo preventing new tst-wordexp-reuse-mem to run
+    - Fix incorrect handling of DNS responses in gethostbyaddr and
+      gethostbyaddr_r (CVE-2026-4437).  Closes: #1131435.
+    - Fix invalid DNS hostnames returned by gethostbyaddr and
+      gethostbyaddr_r (CVE-2026-4438).  Closes: #1131887.
+    - Fix random failure of tst-link-map-contiguous-ldso.
+    - Fix a possible crash due to an assertion failure when converting
+      inputs from the IBM139x character sets (CVE-2026-4046).  Closes:
+      #1132499.
+  * d/p/amd64/local-revert-x86-64-add-GLIBC_ABI_DT_X86_64_PLT-version.diff:
+    revert addition of the GLIBC_ABI_DT_X86_64_PLT symbol version used as ABI
+    flag, as the dpkg-shlibdeps version in bookworm is not able to handle it
+    (see #1122107).
+
+ -- Aurelien Jarno <[email protected]>  Mon, 27 Apr 2026 22:14:33 +0200
+
 glibc (2.36-9+deb12u13) bookworm; urgency=medium
 
   * debian/patches/git-updates.diff: update from upstream stable branch:
diff --git a/debian/patches/amd64/local-revert-x86-64-add-GLIBC_ABI_DT_X86_64_PLT-version.diff b/debian/patches/amd64/local-revert-x86-64-add-GLIBC_ABI_DT_X86_64_PLT-version.diff
new file mode 100644
index 00000000..829c7593
--- /dev/null
+++ b/debian/patches/amd64/local-revert-x86-64-add-GLIBC_ABI_DT_X86_64_PLT-version.diff
@@ -0,0 +1,50 @@
+From cc8046413227196540f7f3106739e91e6e8a86d6 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <[email protected]>
+Date: Sat, 7 Mar 2026 23:26:12 +0100
+Subject: [PATCH] Revert "x86-64: Add GLIBC_ABI_DT_X86_64_PLT [BZ #33212]"
+
+This reverts commit 99338e3841dd8dcc36e35c274e1063c33b5e5e87.
+---
+ sysdeps/x86_64/Makefile | 9 ---------
+ sysdeps/x86_64/Versions | 5 -----
+ 2 files changed, 14 deletions(-)
+
+diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile
+index f173c5ef4a..c19bef2dec 100644
+--- a/sysdeps/x86_64/Makefile
++++ b/sysdeps/x86_64/Makefile
+@@ -190,15 +190,6 @@ endif
+ 
+ tests-internal += tst-x86-64-tls-1
+ 
+-tests-special += $(objpfx)check-dt-x86-64-plt.out
+-
+-$(objpfx)check-dt-x86-64-plt.out: $(common-objpfx)libc.so
+-       LC_ALL=C $(READELF) -V -W $< \
+-               | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \
+-               | grep GLIBC_ABI_DT_X86_64_PLT > $@; \
+-       $(evaluate-test)
+-generated += check-dt-x86-64-plt.out
+-
+ endif # $(subdir) == elf
+ 
+ ifeq ($(subdir),csu)
+diff --git a/sysdeps/x86_64/Versions b/sysdeps/x86_64/Versions
+index 6a989ad3b3..e94758b236 100644
+--- a/sysdeps/x86_64/Versions
++++ b/sysdeps/x86_64/Versions
+@@ -5,11 +5,6 @@ libc {
+   GLIBC_2.13 {
+     __fentry__;
+   }
+-  GLIBC_ABI_DT_X86_64_PLT {
+-    # This symbol is used only for empty version map and will be removed
+-    # by scripts/versions.awk.
+-    __placeholder_only_for_empty_version_map;
+-  }
+ }
+ libm {
+   GLIBC_2.1 {
+-- 
+2.51.0
+
diff --git a/debian/patches/git-updates.diff b/debian/patches/git-updates.diff
index 361d0520..6655f339 100644
--- a/debian/patches/git-updates.diff
+++ b/debian/patches/git-updates.diff
@@ -85,10 +85,10 @@ index d1e139d03c..09c0cf8357 100644
  else	   					# -s
  verbose	:=
 diff --git a/NEWS b/NEWS
-index f61e521fc8..60ac79f4e6 100644
+index f61e521fc8..127817782f 100644
 --- a/NEWS
 +++ b/NEWS
-@@ -5,6 +5,117 @@ See the end for copying conditions.
+@@ -5,6 +5,123 @@ See the end for copying conditions.
  Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
  using `glibc' in the "product" field.
  
@@ -138,6 +138,9 @@ index f61e521fc8..60ac79f4e6 100644
 +  information, which may lead to a buffer overflow if the message string
 +  size aligns to page size.
 +
++  GLIBC-SA-2026-0003: wordexp with WRDE_REUSE and WRDE_APPEND may return
++  uninitialized memory (CVE-2025-15281).
++
 +The following bugs are resolved with this release:
 +
 +  [12154] Do not fail DNS resolution for CNAMEs which are not host names
@@ -193,6 +196,7 @@ index f61e521fc8..60ac79f4e6 100644
 +  [31185] Incorrect thread point access in _dl_tlsdesc_undefweak and _dl_tlsdesc_dynamic
 +  [31476] resolv: Track single-request fallback via _res._flags
 +  [31890] resolv: Allow short error responses to match any DNS query
++  [31943] _dl_find_object can fail if ld.so contains gaps between load segments
 +  [31965] rseq extension mechanism does not work as intended
 +  [31968] mremap implementation in C does not handle arguments correctly
 +  [32052] Name space violation in fortify wrappers
@@ -202,6 +206,8 @@ index f61e521fc8..60ac79f4e6 100644
 +  [32582] Fix underallocation of abort_msg_s struct (CVE-2025-0395)
 +  [32987] elf: Fix subprocess status handling for tst-dlopen-sgid
 +  [33185] Fix double-free after allocation failure in regcomp
++  [33814] glob: wordexp with WRDE_REUSE and WRDE_APPEND may return
++    uninitialized memory
 +
  Version 2.36
  
@@ -532,7 +538,7 @@ index 2696dde4b1..9b07b4e132 100644
  
  void *
 diff --git a/elf/Makefile b/elf/Makefile
-index fd77d0c7c8..3e08a8046d 100644
+index fd77d0c7c8..97befdaf02 100644
 --- a/elf/Makefile
 +++ b/elf/Makefile
 @@ -53,6 +53,7 @@ routines = \
@@ -584,7 +590,27 @@ index fd77d0c7c8..3e08a8046d 100644
    tst-relsort1 \
    tst-ro-dynamic \
    tst-rtld-run-static \
-@@ -631,6 +638,7 @@ ifeq ($(run-built-tests),yes)
+@@ -497,6 +504,8 @@ tests-internal += \
+   tst-dl_find_object \
+   tst-dl_find_object-threads \
+   tst-dlmopen2 \
++  tst-link-map-contiguous-ldso \
++  tst-link-map-contiguous-libc \
+   tst-ptrguard1 \
+   tst-stackguard1 \
+   tst-tls-surplus \
+@@ -508,6 +517,10 @@ tests-internal += \
+   unload2 \
+   # tests-internal
+ 
++ifeq ($(build-hardcoded-path-in-tests),yes)
++tests-internal += tst-link-map-contiguous-main
++endif
++
+ tests-container += \
+   tst-dlopen-self-container \
+   tst-dlopen-tlsmodid-container \
+@@ -631,6 +644,7 @@ ifeq ($(run-built-tests),yes)
  tests-special += \
    $(objpfx)noload-mem.out \
    $(objpfx)tst-ldconfig-X.out \
@@ -592,7 +618,7 @@ index fd77d0c7c8..3e08a8046d 100644
    $(objpfx)tst-leaks1-mem.out \
    $(objpfx)tst-rtld-help.out \
    # tests-special
-@@ -765,6 +773,8 @@ modules-names += \
+@@ -765,6 +779,8 @@ modules-names += \
    tst-alignmod3 \
    tst-array2dep \
    tst-array5dep \
@@ -601,7 +627,7 @@ index fd77d0c7c8..3e08a8046d 100644
    tst-audit11mod1 \
    tst-audit11mod2 \
    tst-audit12mod1 \
-@@ -798,6 +808,7 @@ modules-names += \
+@@ -798,6 +814,7 @@ modules-names += \
    tst-auditmanymod7 \
    tst-auditmanymod8 \
    tst-auditmanymod9 \
@@ -609,7 +635,7 @@ index fd77d0c7c8..3e08a8046d 100644
    tst-auditmod1 \
    tst-auditmod9a \
    tst-auditmod9b \
-@@ -834,6 +845,9 @@ modules-names += \
+@@ -834,6 +851,9 @@ modules-names += \
    tst-dlmopen1mod \
    tst-dlmopen-dlerror-mod \
    tst-dlmopen-gethostbyname-mod \
@@ -619,7 +645,7 @@ index fd77d0c7c8..3e08a8046d 100644
    tst-dlopenfaillinkmod \
    tst-dlopenfailmod1 \
    tst-dlopenfailmod2 \
-@@ -866,6 +880,23 @@ modules-names += \
+@@ -866,6 +886,23 @@ modules-names += \
    tst-null-argv-lib \
    tst-p_alignmod-base \
    tst-p_alignmod3 \
@@ -643,7 +669,7 @@ index fd77d0c7c8..3e08a8046d 100644
    tst-relsort1mod1 \
    tst-relsort1mod2 \
    tst-ro-dynamic-mod \
-@@ -990,23 +1021,8 @@ modules-names += tst-gnu2-tls1mod
+@@ -990,23 +1027,8 @@ modules-names += tst-gnu2-tls1mod
  $(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
  tst-gnu2-tls1mod.so-no-z-defs = yes
  CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
@@ -668,7 +694,7 @@ index fd77d0c7c8..3e08a8046d 100644
  ifeq (yes,$(have-protected-data))
  modules-names += tst-protected1moda tst-protected1modb
  tests += tst-protected1a tst-protected1b
-@@ -2410,6 +2426,11 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
+@@ -2410,6 +2432,11 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
  		 '$(run-program-env)' > $@; \
  	$(evaluate-test)
  
@@ -680,7 +706,7 @@ index fd77d0c7c8..3e08a8046d 100644
  # Test static linking of all the libraries we can possibly link
  # together.  Note that in some configurations this may be less than the
  # complete list of libraries we build but we try to maxmimize this list.
-@@ -2967,3 +2988,35 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \
+@@ -2967,3 +2994,35 @@ $(objpfx)tst-tls-allocation-failure-static-patched.out: \
  	grep -q '^Fatal glibc error: Cannot allocate TLS block$$' $@ \
  	  && grep -q '^status: 127$$' $@; \
  	  $(evaluate-test)
@@ -878,7 +904,7 @@ index bcd6e206e9..ef909d8c66 100644
        if (tls_free_end == GL(dl_tls_static_used))
  	GL(dl_tls_static_used) = tls_free_start;
 diff --git a/elf/dl-find_object.c b/elf/dl-find_object.c
-index 4d5831b6f4..2e5b456c11 100644
+index 4d5831b6f4..cb8555a543 100644
 --- a/elf/dl-find_object.c
 +++ b/elf/dl-find_object.c
 @@ -46,7 +46,7 @@ _dl_find_object_slow (void *pc, struct dl_find_object *result)
@@ -890,6 +916,134 @@ index 4d5831b6f4..2e5b456c11 100644
          }
  
    /* Object not found.  */
+@@ -465,6 +465,37 @@ _dl_find_object (void *pc1, struct dl_find_object *result)
+ }
+ rtld_hidden_def (_dl_find_object)
+ 
++/* Subroutine of _dlfo_process_initial to split out noncontigous link
++   maps.  NODELETE is the number of used _dlfo_nodelete_mappings
++   elements.  It is incremented as needed, and the new NODELETE value
++   is returned.  */
++static size_t
++_dlfo_process_initial_noncontiguous_map (struct link_map *map,
++                                         size_t nodelete)
++{
++  struct dl_find_object_internal dlfo;
++  _dl_find_object_from_map (map, &dlfo);
++
++  /* PT_LOAD segments for a non-contiguous link map are added to the
++     non-closeable mappings.  */
++  const ElfW(Phdr) *ph = map->l_phdr;
++  const ElfW(Phdr) *ph_end = map->l_phdr + map->l_phnum;
++  for (; ph < ph_end; ++ph)
++    if (ph->p_type == PT_LOAD)
++      {
++        if (_dlfo_nodelete_mappings != NULL)
++          {
++            /* Second pass only.  */
++            _dlfo_nodelete_mappings[nodelete] = dlfo;
++            ElfW(Addr) start = ph->p_vaddr + map->l_addr;
++            _dlfo_nodelete_mappings[nodelete].map_start = start;
++            _dlfo_nodelete_mappings[nodelete].map_end = start + ph->p_memsz;
++          }
++        ++nodelete;
++      }
++  return nodelete;
++}
++
+ /* _dlfo_process_initial is called twice.  First to compute the array
+    sizes from the initial loaded mappings.  Second to fill in the
+    bases and infos arrays with the (still unsorted) data.  Returns the
+@@ -476,29 +507,8 @@ _dlfo_process_initial (void)
+ 
+   size_t nodelete = 0;
+   if (!main_map->l_contiguous)
+-    {
+-      struct dl_find_object_internal dlfo;
+-      _dl_find_object_from_map (main_map, &dlfo);
+-
+-      /* PT_LOAD segments for a non-contiguous are added to the
+-         non-closeable mappings.  */
+-      for (const ElfW(Phdr) *ph = main_map->l_phdr,
+-             *ph_end = main_map->l_phdr + main_map->l_phnum;
+-           ph < ph_end; ++ph)
+-        if (ph->p_type == PT_LOAD)
+-          {
+-            if (_dlfo_nodelete_mappings != NULL)
+-              {
+-                /* Second pass only.  */
+-                _dlfo_nodelete_mappings[nodelete] = dlfo;
+-                _dlfo_nodelete_mappings[nodelete].map_start
+-                  = ph->p_vaddr + main_map->l_addr;
+-                _dlfo_nodelete_mappings[nodelete].map_end
+-                  = _dlfo_nodelete_mappings[nodelete].map_start + ph->p_memsz;
+-              }
+-            ++nodelete;
+-          }
+-    }
++    /* Contiguous case already handled in _dl_find_object_init.  */
++    nodelete = _dlfo_process_initial_noncontiguous_map (main_map, nodelete);
+ 
+   size_t loaded = 0;
+   for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
+@@ -510,11 +520,22 @@ _dlfo_process_initial (void)
+           /* lt_library link maps are implicitly NODELETE.  */
+           if (l->l_type == lt_library || l->l_nodelete_active)
+             {
+-              if (_dlfo_nodelete_mappings != NULL)
+-                /* Second pass only.  */
+-                _dl_find_object_from_map
+-                  (l, _dlfo_nodelete_mappings + nodelete);
+-              ++nodelete;
++              /* The kernel may have loaded ld.so with gaps.   */
++              if (!l->l_contiguous
++#ifdef SHARED
++                  && l == &GL(dl_rtld_map)
++#endif
++                  )
++                nodelete
++                  = _dlfo_process_initial_noncontiguous_map (l, nodelete);
++              else
++                {
++                  if (_dlfo_nodelete_mappings != NULL)
++                    /* Second pass only.  */
++                    _dl_find_object_from_map
++                      (l, _dlfo_nodelete_mappings + nodelete);
++                  ++nodelete;
++                }
+             }
+           else if (l->l_type == lt_loaded)
+             {
+@@ -756,7 +777,6 @@ _dl_find_object_update_1 (struct link_map **loaded, size_t count)
+           /* Prefer newly loaded link map.  */
+           assert (loaded_index1 > 0);
+           _dl_find_object_from_map (loaded[loaded_index1 - 1], dlfo);
+-          loaded[loaded_index1 -  1]->l_find_object_processed = 1;
+           --loaded_index1;
+         }
+ 
+diff --git a/elf/dl-find_object.h b/elf/dl-find_object.h
+index 3b49877e0e..9d13163ccd 100644
+--- a/elf/dl-find_object.h
++++ b/elf/dl-find_object.h
+@@ -87,7 +87,7 @@ _dl_find_object_to_external (struct dl_find_object_internal *internal,
+ }
+ 
+ /* Extract the object location data from a link map and writes it to
+-   *RESULT using relaxed MO stores.  */
++   *RESULT using relaxed MO stores.  Set L->l_find_object_processed.  */
+ static void __attribute__ ((unused))
+ _dl_find_object_from_map (struct link_map *l,
+                           struct dl_find_object_internal *result)
+@@ -100,6 +100,8 @@ _dl_find_object_from_map (struct link_map *l,
+   atomic_store_relaxed (&result->eh_dbase, (void *) l->l_info[DT_PLTGOT]);
+ #endif
+ 
++  l->l_find_object_processed = 1;
++
+   for (const ElfW(Phdr) *ph = l->l_phdr, *ph_end = l->l_phdr + l->l_phnum;
+        ph < ph_end; ++ph)
+     if (ph->p_type == DLFO_EH_SEGMENT_TYPE)
 diff --git a/elf/dl-fini.c b/elf/dl-fini.c
 index 030b1fcbcd..50ff94db16 100644
 --- a/elf/dl-fini.c
@@ -1875,7 +2029,7 @@ index ca00dd1fe2..3c5e273f2b 100644
  else						# -s
  verbose	:=
 diff --git a/elf/rtld.c b/elf/rtld.c
-index cbbaf4a331..6e40893e52 100644
+index cbbaf4a331..bb3fc4806a 100644
 --- a/elf/rtld.c
 +++ b/elf/rtld.c
 @@ -791,6 +791,8 @@ init_tls (size_t naudit)
@@ -1887,7 +2041,103 @@ index cbbaf4a331..6e40893e52 100644
    /* Store for detection of the special case by __tls_get_addr
       so it knows not to pass this dtv to the normal realloc.  */
    GL(dl_initial_dtv) = GET_DTV (tcbp);
-@@ -2122,6 +2124,12 @@ dl_main (const ElfW(Phdr) *phdr,
+@@ -1293,6 +1295,60 @@ rtld_setup_main_map (struct link_map *main_map)
+   return has_interp;
+ }
+ 
++/* Set up the program header information for the dynamic linker
++   itself.  It can be accessed via _r_debug and dl_iterate_phdr
++   callbacks, and it is used by _dl_find_object.  */
++static void
++rtld_setup_phdr (void)
++{
++  /* Starting from binutils-2.23, the linker will define the magic
++     symbol __ehdr_start to point to our own ELF header if it is
++     visible in a segment that also includes the phdrs.  */
++
++  const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start;
++  assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
++  assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
++
++  const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff;
++
++  GL(dl_rtld_map).l_phdr = rtld_phdr;
++  GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
++
++
++  GL(dl_rtld_map).l_contiguous = 1;
++  /* The linker may not have produced a contiguous object.  The kernel
++     will load the object with actual gaps (unlike the glibc loader
++     for shared objects, which always produces a contiguous mapping).
++     See similar logic in rtld_setup_main_map above.  */
++  {
++    ElfW(Addr) expected_load_address = 0;
++    for (const ElfW(Phdr) *ph = rtld_phdr; ph < &rtld_phdr[rtld_ehdr->e_phnum];
++	 ++ph)
++      if (ph->p_type == PT_LOAD)
++	{
++	  ElfW(Addr) mapstart = ph->p_vaddr & ~(GLRO(dl_pagesize) - 1);
++	  if (GL(dl_rtld_map).l_contiguous && expected_load_address != 0
++	      && expected_load_address != mapstart)
++	    GL(dl_rtld_map).l_contiguous = 0;
++	  ElfW(Addr) allocend = ph->p_vaddr + ph->p_memsz;
++	  /* The next expected address is the page following this load
++	     segment.  */
++	  expected_load_address = ((allocend + GLRO(dl_pagesize) - 1)
++				   & ~(GLRO(dl_pagesize) - 1));
++	}
++  }
++
++  /* PT_GNU_RELRO is usually the last phdr.  */
++  size_t cnt = rtld_ehdr->e_phnum;
++  while (cnt-- > 0)
++    if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
++      {
++	GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr;
++	GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz;
++	break;
++      }
++}
++
+ /* Adjusts the contents of the stack and related globals for the user
+    entry point.  The ld.so processed skip_args arguments and bumped
+    _dl_argv and _dl_argc accordingly.  Those arguments are removed from
+@@ -1762,33 +1818,7 @@ dl_main (const ElfW(Phdr) *phdr,
+   ++GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
+   ++GL(dl_load_adds);
+ 
+-  /* Starting from binutils-2.23, the linker will define the magic symbol
+-     __ehdr_start to point to our own ELF header if it is visible in a
+-     segment that also includes the phdrs.  If that's not available, we use
+-     the old method that assumes the beginning of the file is part of the
+-     lowest-addressed PT_LOAD segment.  */
+-
+-  /* Set up the program header information for the dynamic linker
+-     itself.  It is needed in the dl_iterate_phdr callbacks.  */
+-  const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start;
+-  assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
+-  assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
+-
+-  const ElfW(Phdr) *rtld_phdr = (const void *) rtld_ehdr + rtld_ehdr->e_phoff;
+-
+-  GL(dl_rtld_map).l_phdr = rtld_phdr;
+-  GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
+-
+-
+-  /* PT_GNU_RELRO is usually the last phdr.  */
+-  size_t cnt = rtld_ehdr->e_phnum;
+-  while (cnt-- > 0)
+-    if (rtld_phdr[cnt].p_type == PT_GNU_RELRO)
+-      {
+-	GL(dl_rtld_map).l_relro_addr = rtld_phdr[cnt].p_vaddr;
+-	GL(dl_rtld_map).l_relro_size = rtld_phdr[cnt].p_memsz;
+-	break;
+-      }
++  rtld_setup_phdr ();
+ 
+   /* Add the dynamic linker to the TLS list if it also uses TLS.  */
+   if (GL(dl_rtld_map).l_tls_blocksize != 0)
+@@ -2122,6 +2152,12 @@ dl_main (const ElfW(Phdr) *phdr,
  	    if (l->l_faked)
  	      /* The library was not found.  */
  	      _dl_printf ("\t%s => not found\n",  l->l_libname->name);
@@ -2395,6 +2645,284 @@ index 0000000000..ec937bf4ec
 +esac
 +
 +exit $errors
+diff --git a/elf/tst-link-map-contiguous-ldso.c b/elf/tst-link-map-contiguous-ldso.c
+new file mode 100644
+index 0000000000..f0e26682f2
+--- /dev/null
++++ b/elf/tst-link-map-contiguous-ldso.c
+@@ -0,0 +1,158 @@
++/* Check that _dl_find_object behavior matches up with gaps.
++   Copyright (C) 2025 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <dlfcn.h>
++#include <gnu/lib-names.h>
++#include <inttypes.h>
++#include <link.h>
++#include <stdbool.h>
++#include <stdio.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/xdlfcn.h>
++#include <support/xunistd.h>
++#include <support/xstdio.h>
++#include <sys/mman.h>
++#include <unistd.h>
++
++/* Slow path in case we cannot find a gap with mmap (when the runtime has
++   mapped all the pages in the gap for some reason).  */
++static bool
++find_gap_with_proc_self_map (const struct link_map *l)
++{
++  int pagesize = getpagesize ();
++
++  support_need_proc ("Reads /proc/self/maps to find gap in ld.so mapping");
++
++  /* Parse /proc/self/maps and find all the mappings in the ld.so range
++     but not from ld.so.  */
++  FILE *f = xfopen ("/proc/self/maps", "r");
++  char *line = NULL, *path_ldso = NULL;
++  size_t len;
++  bool found = false;
++  while (xgetline (&line, &len, f))
++    {
++      uintptr_t from, to;
++      char *path = NULL;
++      int r = sscanf (line, "%" SCNxPTR "-%" SCNxPTR "%*s%*s%*s%*s%ms",
++                      &from, &to, &path);
++
++      TEST_VERIFY (r == 2 || r == 3);
++      TEST_COMPARE (from % pagesize, 0);
++      TEST_COMPARE (to % pagesize, 0);
++
++      if (path_ldso == NULL && l->l_map_start == from)
++        {
++          TEST_COMPARE (r, 3);
++          path_ldso = path;
++          continue;
++        }
++
++      if (from > l->l_map_start && to < l->l_map_end
++          && (r == 2 || (path_ldso != NULL && strcmp (path, path_ldso))))
++        {
++          if (r == 2)
++            printf ("info: anonymous mapping found at 0x%" PRIxPTR " - 0x%"
++                    PRIxPTR "\n", from, to);
++          else
++            printf ("info: object \"%s\" found at 0x%" PRIxPTR " - 0x%"
++                    PRIxPTR "\n", path, from, to);
++
++          found = true;
++        }
++
++      free (path);
++    }
++
++  free (path_ldso);
++  free (line);
++  xfclose (f);
++  return found;
++}
++
++static int
++do_test (void)
++{
++  struct link_map *l = xdlopen (LD_SO, RTLD_NOW);
++  if (!l->l_contiguous)
++    {
++      puts ("info: ld.so link map is not contiguous");
++
++      /* Try to find holes by probing with mmap.  */
++      int pagesize = getpagesize ();
++      bool gap_found = false;
++      ElfW(Addr) addr = l->l_map_start;
++      TEST_COMPARE (addr % pagesize, 0);
++      while (addr < l->l_map_end)
++        {
++          void *expected = (void *) addr;
++          void *ptr = xmmap (expected, 1, PROT_READ | PROT_WRITE,
++                             MAP_PRIVATE | MAP_ANONYMOUS, -1);
++          struct dl_find_object dlfo;
++          int dlfo_ret = _dl_find_object (expected, &dlfo);
++          if (ptr == expected)
++            {
++              if (dlfo_ret < 0)
++                {
++                  TEST_COMPARE (dlfo_ret, -1);
++                  printf ("info: hole without mapping data found at %p\n", ptr);
++                }
++              else
++                FAIL ("object \"%s\" found in gap at %p",
++                      dlfo.dlfo_link_map->l_name, ptr);
++              gap_found = true;
++            }
++          else if (dlfo_ret == 0)
++            {
++              if ((void *) dlfo.dlfo_link_map != (void *) l)
++                {
++                  printf ("info: object \"%s\" found at %p\n",
++                          dlfo.dlfo_link_map->l_name, expected);
++                  gap_found = true;
++                }
++            }
++          else
++            TEST_COMPARE (dlfo_ret, -1);
++
++          xmunmap (ptr, 1);
++          addr += pagesize;
++        }
++
++      if (!gap_found && !find_gap_with_proc_self_map (l))
++        FAIL ("no ld.so gap found");
++    }
++  else
++    {
++      puts ("info: ld.so link map is contiguous");
++
++      /* Assert that ld.so is truly contiguous in memory.  */
++      volatile long int *p = (volatile long int *) l->l_map_start;
++      volatile long int *end = (volatile long int *) l->l_map_end;
++      while (p < end)
++        {
++          *p;
++          ++p;
++        }
++    }
++
++  xdlclose (l);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/elf/tst-link-map-contiguous-libc.c b/elf/tst-link-map-contiguous-libc.c
+new file mode 100644
+index 0000000000..eb5728c765
+--- /dev/null
++++ b/elf/tst-link-map-contiguous-libc.c
+@@ -0,0 +1,57 @@
++/* Check that the entire libc.so program image is readable if contiguous.
++   Copyright (C) 2025 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <gnu/lib-names.h>
++#include <link.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++#include <support/xunistd.h>
++#include <sys/mman.h>
++#include <unistd.h>
++
++static int
++do_test (void)
++{
++  struct link_map *l = xdlopen (LIBC_SO, RTLD_NOW);
++
++  /* The dynamic loader fills holes with PROT_NONE mappings.  */
++  if (!l->l_contiguous)
++    FAIL_EXIT1 ("libc.so link map is not contiguous");
++
++  /* Direct probing does not work because not everything is readable
++     due to PROT_NONE mappings.  */
++  int pagesize = getpagesize ();
++  ElfW(Addr) addr = l->l_map_start;
++  TEST_COMPARE (addr % pagesize, 0);
++  while (addr < l->l_map_end)
++    {
++      void *expected = (void *) addr;
++      void *ptr = xmmap (expected, 1, PROT_READ | PROT_WRITE,
++                         MAP_PRIVATE | MAP_ANONYMOUS, -1);
++      if (ptr == expected)
++        FAIL ("hole in libc.so memory image after %lu bytes",
++              (unsigned long int) (addr - l->l_map_start));
++      xmunmap (ptr, 1);
++      addr += pagesize;
++    }
++
++  xdlclose (l);
++
++  return 0;
++}
++#include <support/test-driver.c>
+diff --git a/elf/tst-link-map-contiguous-main.c b/elf/tst-link-map-contiguous-main.c
+new file mode 100644
+index 0000000000..2d1a054f0f
+--- /dev/null
++++ b/elf/tst-link-map-contiguous-main.c
+@@ -0,0 +1,45 @@
++/* Check that the entire main program image is readable if contiguous.
++   Copyright (C) 2025 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <link.h>
++#include <support/check.h>
++#include <support/xdlfcn.h>
++
++static int
++do_test (void)
++{
++  struct link_map *l = xdlopen ("", RTLD_NOW);
++  if (!l->l_contiguous)
++    FAIL_UNSUPPORTED ("main link map is not contiguous");
++
++  /* This check only works if the kernel loaded the main program.  The
++     dynamic loader replaces gaps with PROT_NONE mappings, resulting
++     in faults.  */
++  volatile long int *p = (volatile long int *) l->l_map_start;
++  volatile long int *end = (volatile long int *) l->l_map_end;
++  while (p < end)
++    {
++      *p;
++      ++p;
++    }
++
++  xdlclose (l);
++
++  return 0;
++}
++#include <support/test-driver.c>
 diff --git a/elf/tst-recursive-tls.c b/elf/tst-recursive-tls.c
 new file mode 100644
 index 0000000000..716d1f783a
@@ -3101,7 +3629,7 @@ index debb96b322..b72933b526 100644
  
  	      free (conf);
 diff --git a/iconvdata/Makefile b/iconvdata/Makefile
-index f4c089ed5d..d01b3fcab6 100644
+index f4c089ed5d..1ca3a193c7 100644
 --- a/iconvdata/Makefile
 +++ b/iconvdata/Makefile
 @@ -75,7 +75,8 @@ ifeq (yes,$(build-shared))
@@ -3110,19 +3638,148 @@ index f4c089ed5d..d01b3fcab6 100644
  	bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
 -	bug-iconv13 bug-iconv14 bug-iconv15
 +	bug-iconv13 bug-iconv14 bug-iconv15 \
-+	tst-iconv-iso-2022-cn-ext
++	tst-iconv-iso-2022-cn-ext tst-bug33980
  ifeq ($(have-thread-library),yes)
  tests += bug-iconv3
  endif
-@@ -330,6 +331,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
+@@ -330,6 +331,10 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
  			  $(addprefix $(objpfx),$(modules.so))
  $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
  			  $(addprefix $(objpfx),$(modules.so))
 +$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
 +					$(addprefix $(objpfx),$(modules.so))
++$(objpfx)tst-bug33980.out: $(addprefix $(objpfx), $(gconv-modules)) \
++			   $(addprefix $(objpfx),$(modules.so))
  
  $(objpfx)iconv-test.out: run-iconv-test.sh \
  			 $(addprefix $(objpfx), $(gconv-modules)) \
+diff --git a/iconvdata/ansi_x3.110.c b/iconvdata/ansi_x3.110.c
+index fa2f6b46e5..6c9e5a024e 100644
+--- a/iconvdata/ansi_x3.110.c
++++ b/iconvdata/ansi_x3.110.c
+@@ -407,7 +407,7 @@ static const char from_ucs4[][2] =
+ 	   is also available.  */					      \
+ 	uint32_t ch2;							      \
+ 									      \
+-	if (inptr + 1 >= inend)						      \
++	if (inend - inptr <= 1)						      \
+ 	  {								      \
+ 	    /* The second character is not available.  */		      \
+ 	    result = __GCONV_INCOMPLETE_INPUT;				      \
+diff --git a/iconvdata/ibm1364.c b/iconvdata/ibm1364.c
+index ce3172416c..e79f98a769 100644
+--- a/iconvdata/ibm1364.c
++++ b/iconvdata/ibm1364.c
+@@ -67,12 +67,29 @@
+ 
+ /* Since this is a stateful encoding we have to provide code which resets
+    the output state to the initial state.  This has to be done during the
+-   flushing.  */
++   flushing.  For the to-internal direction (FROM_DIRECTION is true),
++   there may be a pending character that needs flushing.  */
+ #define EMIT_SHIFT_TO_INIT \
+   if ((data->__statep->__count & ~7) != sb)				      \
+     {									      \
+       if (FROM_DIRECTION)						      \
+-	data->__statep->__count &= 7;					      \
++	{								      \
++	  uint32_t ch = data->__statep->__count >> 7;			      \
++	  if (__glibc_unlikely (ch != 0))				      \
++	    {								      \
++	      if (__glibc_unlikely (outend - outbuf < 4))		      \
++		status = __GCONV_FULL_OUTPUT;				      \
++	      else							      \
++		{							      \
++		  put32u (outbuf, ch);					      \
++		  outbuf += 4;						      \
++		  /* Clear character and db bit.  */			      \
++		  data->__statep->__count &= 7;				      \
++		}							      \
++	    }								      \
++	  else								      \
++	    data->__statep->__count &= 7;				      \
++	}								      \
+       else								      \
+ 	{								      \
+ 	  /* We are not in the initial state.  To switch back we have	      \
+@@ -99,11 +116,13 @@
+     *curcsp = save_curcs
+ 
+ 
+-/* Current codeset type.  */
++/* Current codeset type.  The bit is stored in the __count variable of
++   the conversion state.  If the db bit is set, bit 7 and above store
++   a pending UCS-4 code point if non-zero.  */
+ enum
+ {
+-  sb = 0,
+-  db = 64
++  sb = 0,			/* Single byte mode.  */
++  db = 64			/* Double byte mode.  */
+ };
+ 
+ 
+@@ -119,21 +138,29 @@ enum
+       }									      \
+     else								      \
+       {									      \
+-	/* This is a combined character.  Make sure we have room.  */	      \
+-	if (__glibc_unlikely (outptr + 8 > outend))			      \
+-	  {								      \
+-	    result = __GCONV_FULL_OUTPUT;				      \
+-	    break;							      \
+-	  }								      \
+-									      \
+ 	const struct divide *cmbp					      \
+ 	  = &DB_TO_UCS4_COMB[ch - __TO_UCS4_COMBINED_MIN];		      \
+ 	assert (cmbp->res1 != 0 && cmbp->res2 != 0);			      \
+ 									      \
+ 	put32 (outptr, cmbp->res1);					      \
+ 	outptr += 4;							      \
+-	put32 (outptr, cmbp->res2);					      \
+-	outptr += 4;							      \
++									      \
++	/* See whether we have room for the second character.  */	      \
++	if (outend - outptr >= 4)					      \
++	  {								      \
++	    put32 (outptr, cmbp->res2);					      \
++	    outptr += 4;						      \
++	  }								      \
++	else								      \
++	  {								      \
++	    /* Otherwise store only the first character now, and	      \
++	       put the second one into the queue.  */			      \
++	    curcs |= cmbp->res2 << 7;					      \
++	    inptr += 2;							      \
++	    /* Tell the caller why we terminate the loop.  */		      \
++	    result = __GCONV_FULL_OUTPUT;				      \
++	    break;							      \
++	  }								      \
+       }									      \
+   }
+ #else
+@@ -153,7 +180,20 @@ enum
+ #define LOOPFCT 		FROM_LOOP
+ #define BODY \
+   {									      \
+-    uint32_t ch = *inptr;						      \
++    uint32_t ch;							      \
++									      \
++    ch = curcs >> 7;							      \
++    if (__glibc_unlikely (ch != 0))					      \
++      {									      \
++	put32 (outptr, ch);						      \
++	outptr += 4;							      \
++	/* Remove the pending character, but preserve state bits.  */	      \
++	curcs &= (1 << 7) - 1;						      \
++	continue;							      \
++      }									      \
++									      \
++    /* Otherwise read the next input byte.  */				      \
++    ch = *inptr;							      \
+ 									      \
+     if (__builtin_expect (ch, 0) == SO)					      \
+       {									      \
 diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
 index e09f358cad..2cc478a8c6 100644
 --- a/iconvdata/iso-2022-cn-ext.c
@@ -3153,6 +3810,165 @@ index e09f358cad..2cc478a8c6 100644
  		assert ((used >> 5) >= 3 && (used >> 5) <= 7);		      \
  		escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2;		      \
  		*outptr++ = ESC;					      \
+diff --git a/iconvdata/tst-bug33980.c b/iconvdata/tst-bug33980.c
+new file mode 100644
+index 0000000000..c9693e0efe
+--- /dev/null
++++ b/iconvdata/tst-bug33980.c
+@@ -0,0 +1,153 @@
++/* Test for bug 33980: combining characters in IBM1390/IBM1399.
++   Copyright (C) 2026 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <alloc_buffer.h>
++#include <errno.h>
++#include <iconv.h>
++#include <stdbool.h>
++#include <string.h>
++
++#include <support/check.h>
++#include <support/next_to_fault.h>
++#include <support/support.h>
++
++/* Run iconv in a loop with a small output buffer of OUTBUFSIZE bytes
++   starting at OUTBUF.  OUTBUF should be right before an unmapped page
++   so that writing past the end will fault.  Skip SHIFT bytes at the
++   start of the input and output, to exercise different buffer
++   alignment.  TRUNCATE indicates skipped bytes at the end of
++   input (0 and 1 a valid).  */
++static void
++test_one (const char *encoding, unsigned int shift, unsigned int truncate,
++          char *outbuf, size_t outbufsize)
++{
++  /* In IBM1390 and IBM1399, the DBCS code 0xECB5 expands to two
++     Unicode code points when translated.  */
++  static char input[] =
++    {
++      /* 8 letters X.  */
++      0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7, 0xe7,
++      /* SO, 0xECB5, SI: shift to DBCS, special character, shift back.  */
++      0x0e, 0xec, 0xb5, 0x0f
++    };
++
++  /* Expected output after UTF-8 conversion.  */
++  static char expected[] =
++    {
++      'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X',
++      /* U+304B (HIRAGANA LETTER KA).  */
++      0xe3, 0x81, 0x8b,
++      /* U+309A (COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK).  */
++      0xe3, 0x82, 0x9a
++    };
++
++  iconv_t cd = iconv_open ("UTF-8", encoding);
++  TEST_VERIFY_EXIT (cd != (iconv_t) -1);
++
++  char result_storage[64];
++  struct alloc_buffer result_buf
++    = alloc_buffer_create (result_storage, sizeof (result_storage));
++
++  char *inptr = &input[shift];
++  size_t inleft = sizeof (input) - shift - truncate;
++
++  while (inleft > 0)
++    {
++      char *outptr = outbuf;
++      size_t outleft = outbufsize;
++      size_t inleft_before = inleft;
++
++      size_t ret = iconv (cd, &inptr, &inleft, &outptr, &outleft);
++      size_t produced = outptr - outbuf;
++      alloc_buffer_copy_bytes (&result_buf, outbuf, produced);
++
++      if (ret == (size_t) -1 && errno == E2BIG)
++        {
++          if (produced == 0 && inleft == inleft_before)
++            {
++              /* Output buffer too small to make progress.  This is
++                 expected for very small output buffer sizes.  */
++              TEST_VERIFY_EXIT (outbufsize < 3);
++              break;
++            }
++          continue;
++        }
++      if (ret == (size_t) -1)
++        FAIL_EXIT1 ("%s (outbufsize %zu): iconv: %m", encoding, outbufsize);
++      break;
++    }
++
++  /* Flush any pending state (e.g. a buffered combined character).
++     With outbufsize < 3, we could not store the first character, so
++     the second character did not become pending, and there is nothing
++     to flush.  */
++  {
++    char *outptr = outbuf;
++    size_t outleft = outbufsize;
++
++    size_t ret = iconv (cd, NULL, NULL, &outptr, &outleft);
++    TEST_VERIFY_EXIT (ret == 0);
++    size_t produced = outptr - outbuf;
++    alloc_buffer_copy_bytes (&result_buf, outbuf, produced);
++
++    /* Second flush does not provide more data.  */
++    outptr = outbuf;
++    outleft = outbufsize;
++    ret = iconv (cd, NULL, NULL, &outptr, &outleft);
++    TEST_VERIFY_EXIT (ret == 0);
++    TEST_VERIFY (outptr == outbuf);
++  }
++
++  TEST_VERIFY_EXIT (!alloc_buffer_has_failed (&result_buf));
++  size_t result_used
++    = sizeof (result_storage) - alloc_buffer_size (&result_buf);
++
++  if (outbufsize >= 3)
++    {
++      TEST_COMPARE (inleft, 0);
++      TEST_COMPARE (result_used, sizeof (expected) - shift);
++      TEST_COMPARE_BLOB (result_storage, result_used,
++                         &expected[shift], sizeof (expected) - shift);
++    }
++  else
++    /* If the buffer is too small, only the leading X could be converted.  */
++    TEST_COMPARE (result_used, 8 - shift);
++
++  TEST_VERIFY_EXIT (iconv_close (cd) == 0);
++}
++
++static int
++do_test (void)
++{
++  struct support_next_to_fault ntf
++    = support_next_to_fault_allocate (8);
++
++  for (int shift = 0; shift <= 8; ++shift)
++    for (int truncate = 0; truncate < 2; ++truncate)
++      for (size_t outbufsize = 1; outbufsize <= 8; outbufsize++)
++        {
++          char *outbuf = ntf.buffer + ntf.length - outbufsize;
++          test_one ("IBM1390", shift, truncate, outbuf, outbufsize);
++          test_one ("IBM1399", shift, truncate, outbuf, outbufsize);
++        }
++
++  support_next_to_fault_free (&ntf);
++  return 0;
++}
++
++#include <support/test-driver.c>
 diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
 new file mode 100644
 index 0000000000..96a8765fd5
@@ -4080,6 +4896,67 @@ index 0a684a720d..a1ee7928d3 100644
  
                if (n >= 1)
                  narenas_limit = NARENAS_FROM_NCORES (n);
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index bd3c76ed31..53d6e06bb0 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -4949,7 +4949,7 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
+ 
+ 
+   nb = checked_request2size (bytes);
+-  if (nb == 0)
++  if (nb == 0 || alignment > PTRDIFF_MAX)
+     {
+       __set_errno (ENOMEM);
+       return NULL;
+@@ -4960,8 +4960,10 @@ _int_memalign (mstate av, size_t alignment, size_t bytes)
+      request, and then possibly free the leading and trailing space.
+    */
+ 
+-  /* Call malloc with worst case padding to hit alignment. */
+-
++  /* Call malloc with worst case padding to hit alignment.  ALIGNMENT is a
++     power of 2, so it tops out at (PTRDIFF_MAX >> 1) + 1, leaving plenty of
++     space to add MINSIZE and whatever checked_request2size adds to BYTES to
++     get NB.  Consequently, total below also does not overflow.  */
+   m = (char *) (_int_malloc (av, nb + alignment + MINSIZE));
+ 
+   if (m == 0)
+diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c
+index dac3c8086c..e7017981aa 100644
+--- a/malloc/tst-malloc-too-large.c
++++ b/malloc/tst-malloc-too-large.c
+@@ -151,7 +151,6 @@ test_large_allocations (size_t size)
+ }
+ 
+ 
+-static long pagesize;
+ 
+ /* This function tests the following aligned memory allocation functions
+    using several valid alignments and precedes each allocation test with a
+@@ -170,8 +169,8 @@ test_large_aligned_allocations (size_t size)
+ 
+   /* All aligned memory allocation functions expect an alignment that is a
+      power of 2.  Given this, we test each of them with every valid
+-     alignment from 1 thru PAGESIZE.  */
+-  for (align = 1; align <= pagesize; align *= 2)
++     alignment for the type of ALIGN, i.e. until it wraps to 0.  */
++  for (align = 1; align > 0; align <<= 1)
+     {
+       test_setup ();
+ #if __GNUC_PREREQ (7, 0)
+@@ -264,11 +263,6 @@ do_test (void)
+   DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than=");
+ #endif
+ 
+-  /* Aligned memory allocation functions need to be tested up to alignment
+-     size equivalent to page size, which should be a power of 2.  */
+-  pagesize = sysconf (_SC_PAGESIZE);
+-  TEST_VERIFY_EXIT (powerof2 (pagesize));
+-
+   /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e.
+      in the range (SIZE_MAX - 2^14, SIZE_MAX], fail.
+ 
 diff --git a/math/test-tgmath2.c b/math/test-tgmath2.c
 index d758231a89..95897948fb 100644
 --- a/math/test-tgmath2.c
@@ -4963,6 +5840,32 @@ index 5cacb286f3..bbb26607ef 100644
  } __attribute ((aligned (TCB_ALIGNMENT)));
  
  static inline bool
+diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
+index 8a7de8e598..69aa11b0aa 100644
+--- a/nptl/pthread_mutex_trylock.c
++++ b/nptl/pthread_mutex_trylock.c
+@@ -48,7 +48,8 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)
+ 	  return 0;
+ 	}
+ 
+-      if (lll_trylock (mutex->__data.__lock) == 0)
++      if (atomic_load_relaxed (&(mutex->__data.__lock)) == 0
++	  && lll_trylock (mutex->__data.__lock) == 0)
+ 	{
+ 	  /* Record the ownership.  */
+ 	  mutex->__data.__owner = id;
+@@ -71,7 +72,10 @@ ___pthread_mutex_trylock (pthread_mutex_t *mutex)
+       /*FALL THROUGH*/
+     case PTHREAD_MUTEX_ADAPTIVE_NP:
+     case PTHREAD_MUTEX_ERRORCHECK_NP:
+-      if (lll_trylock (mutex->__data.__lock) != 0)
++      /* Mutex type is already loaded, lock check overhead should
++         be minimal.  */
++      if (atomic_load_relaxed (&(mutex->__data.__lock)) != 0
++	  || lll_trylock (mutex->__data.__lock) != 0)
+ 	break;
+ 
+       /* Record the ownership.  */
 diff --git a/nptl/tst-cancel7.c b/nptl/tst-cancel7.c
 index 903457db76..1c80457553 100644
 --- a/nptl/tst-cancel7.c
@@ -5958,18 +6861,56 @@ index fdc5bdd65b..bc32bb132a 100644
  
  static struct hostent host_table_2[] = {
 diff --git a/posix/Makefile b/posix/Makefile
-index d1df7c27cb..336bee4a4a 100644
+index d1df7c27cb..36ae315fad 100644
 --- a/posix/Makefile
 +++ b/posix/Makefile
-@@ -109,7 +109,7 @@ tests		:= test-errno tstgetopt testfnm runtests runptests \
+@@ -109,7 +109,8 @@ tests		:= test-errno tstgetopt testfnm runtests runptests \
  		   tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
  		   bug-regex38 tst-regcomp-truncated tst-spawn-chdir \
  		   tst-wordexp-nocmd tst-execveat tst-spawn5 \
 -		   tst-sched_getaffinity tst-spawn6
-+		   tst-sched_getaffinity tst-spawn6 tst-regcomp-bracket-free
++		   tst-sched_getaffinity tst-spawn6 tst-regcomp-bracket-free \
++		   tst-wordexp-reuse
  
  # Test for the glob symbol version that was replaced in glibc 2.27.
  ifeq ($(have-GLIBC_2.26)$(build-shared),yesyes)
+@@ -156,11 +157,13 @@ generated += $(addprefix wordexp-test-result, 1 2 3 4 5 6 7 8 9 10) \
+ 	     bug-glob2.mtrace bug-glob2-mem.out tst-vfork3-mem.out \
+ 	     tst-vfork3.mtrace getconf.speclist tst-fnmatch-mem.out \
+ 	     tst-fnmatch.mtrace bug-regex36.mtrace \
+-	     testcases.h ptestcases.h
++	     testcases.h ptestcases.h tst-wordexp-reuse-mem.out \
++	     tst-wordexp-reuse.mtrace
+ 
+ ifeq ($(run-built-tests),yes)
+ ifeq (yes,$(build-shared))
+-tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out
++tests-special += $(objpfx)globtest.out $(objpfx)wordexp-tst.out \
++		 $(objpfx)wordexp-tst.out
+ endif
+ endif
+ 
+@@ -174,7 +177,8 @@ tests-special += $(objpfx)bug-regex2-mem.out $(objpfx)bug-regex14-mem.out \
+ 		 $(objpfx)tst-boost-mem.out $(objpfx)tst-getconf.out \
+ 		 $(objpfx)bug-glob2-mem.out $(objpfx)tst-vfork3-mem.out \
+ 		 $(objpfx)tst-fnmatch-mem.out $(objpfx)bug-regex36-mem.out \
+-		 $(objpfx)tst-glob-tilde-mem.out $(objpfx)bug-ga2-mem.out
++		 $(objpfx)tst-glob-tilde-mem.out $(objpfx)bug-ga2-mem.out \
++		 $(objpfx)tst-wordexp-reuse-mem.out
+ endif
+ 
+ include ../Rules
+@@ -451,3 +455,10 @@ $(objpfx)posix-conf-vars-def.h: $(..)scripts/gen-posix-conf-vars.awk \
+ 	$(make-target-directory)
+ 	$(AWK) -f $(filter-out Makefile, $^) > [email protected]
+ 	mv -f [email protected] $@
++
++tst-wordexp-reuse-ENV += MALLOC_TRACE=$(objpfx)tst-wordexp-reuse.mtrace \
++			 LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
++
++$(objpfx)tst-wordexp-reuse-mem.out: $(objpfx)tst-wordexp-reuse.out
++	$(common-objpfx)malloc/mtrace $(objpfx)tst-wordexp-reuse.mtrace > $@; \
++	$(evaluate-test)
 diff --git a/posix/regcomp.c b/posix/regcomp.c
 index 84fc1cc82b..7bd0beeafe 100644
 --- a/posix/regcomp.c
@@ -6243,8 +7184,117 @@ index c8093c5473..39061ce6c5 100644
  
    return 0;
  }
+diff --git a/posix/tst-wordexp-reuse.c b/posix/tst-wordexp-reuse.c
+new file mode 100644
+index 0000000000..3926b9f557
+--- /dev/null
++++ b/posix/tst-wordexp-reuse.c
+@@ -0,0 +1,89 @@
++/* Test for wordexp with WRDE_REUSE flag.
++   Copyright (C) 2026 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <wordexp.h>
++#include <mcheck.h>
++
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++  mtrace ();
++
++  {
++    wordexp_t p = { 0 };
++    TEST_COMPARE (wordexp ("one", &p, 0), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[0], "one");
++    TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[0], "two");
++    wordfree (&p);
++  }
++
++  {
++    wordexp_t p = { .we_offs = 2 };
++    TEST_COMPARE (wordexp ("one", &p, 0), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[0], "one");
++    TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_DOOFFS), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
++    wordfree (&p);
++  }
++
++  {
++    wordexp_t p = { 0 };
++    TEST_COMPARE (wordexp ("one", &p, 0), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[0], "one");
++    TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE | WRDE_APPEND), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[0], "two");
++    wordfree (&p);
++  }
++
++  {
++    wordexp_t p = { .we_offs = 2 };
++    TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one");
++    TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE
++				      | WRDE_DOOFFS), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
++    wordfree (&p);
++  }
++
++  {
++    wordexp_t p = { .we_offs = 2 };
++    TEST_COMPARE (wordexp ("one", &p, WRDE_DOOFFS), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "one");
++    TEST_COMPARE (wordexp ("two", &p, WRDE_REUSE
++				      | WRDE_DOOFFS | WRDE_APPEND), 0);
++    TEST_COMPARE (p.we_wordc, 1);
++    TEST_COMPARE_STRING (p.we_wordv[p.we_offs + 0], "two");
++    wordfree (&p);
++  }
++
++  return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/posix/wordexp.c b/posix/wordexp.c
+index d4cb9c734b..25f5b509a8 100644
+--- a/posix/wordexp.c
++++ b/posix/wordexp.c
+@@ -2219,7 +2219,9 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags)
+     {
+       /* Minimal implementation of WRDE_REUSE for now */
+       wordfree (pwordexp);
++      old_word.we_wordc = 0;
+       old_word.we_wordv = NULL;
++      pwordexp->we_wordc = 0;
+     }
+ 
+   if ((flags & WRDE_APPEND) == 0)
 diff --git a/resolv/Makefile b/resolv/Makefile
-index 5b15321f9b..e5165fb34b 100644
+index 5b15321f9b..d1b22f5b64 100644
 --- a/resolv/Makefile
 +++ b/resolv/Makefile
 @@ -40,12 +40,16 @@ routines := \
@@ -6264,7 +7314,7 @@ index 5b15321f9b..e5165fb34b 100644
    ns_samename \
    nsap_addr \
    nss_dns_functions \
-@@ -89,14 +93,20 @@ tests += \
+@@ -89,21 +93,42 @@ tests += \
    tst-ns_name_pton \
    tst-res_hconf_reorder \
    tst-res_hnok \
@@ -6272,8 +7322,10 @@ index 5b15321f9b..e5165fb34b 100644
    tst-resolv-basic \
    tst-resolv-binary \
 +  tst-resolv-byaddr \
++  tst-resolv-dns-section \
    tst-resolv-edns \
 +  tst-resolv-invalid-cname \
++  tst-resolv-invalid-ptr \
    tst-resolv-network \
    tst-resolv-noaaaa \
 +  tst-resolv-noaaaa-vc \
@@ -6283,9 +7335,10 @@ index 5b15321f9b..e5165fb34b 100644
 +  tst-resolv-semi-failure \
 +  tst-resolv-short-response \
    tst-resolv-trailing \
++  # tests
  
  # This test calls __res_context_send directly, which is not exported
-@@ -104,6 +114,18 @@ tests += \
+ # from libresolv.
  tests-internal += tst-resolv-txnid-collision
  tests-static += tst-resolv-txnid-collision
  
@@ -6304,7 +7357,7 @@ index 5b15321f9b..e5165fb34b 100644
  # These tests need libdl.
  ifeq (yes,$(build-shared))
  tests += \
-@@ -258,8 +280,10 @@ $(objpfx)tst-resolv-ai_idn.out: $(gen-locales)
+@@ -258,8 +283,12 @@ $(objpfx)tst-resolv-ai_idn.out: $(gen-locales)
  $(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales)
  $(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
    $(gen-locales) $(objpfx)tst-no-libidn2.so
@@ -6312,14 +7365,18 @@ index 5b15321f9b..e5165fb34b 100644
  $(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
  $(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
 +$(objpfx)tst-resolv-byaddr: $(objpfx)libresolv.so $(shared-thread-library)
++$(objpfx)tst-resolv-dns-section: $(objpfx)libresolv.so \
++  $(shared-thread-library)
  $(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
  $(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
  $(objpfx)tst-resolv-res_init: $(objpfx)libresolv.so
-@@ -267,11 +291,18 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
+@@ -267,11 +296,20 @@ $(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
    $(shared-thread-library)
  $(objpfx)tst-resolv-res_init-thread: $(objpfx)libresolv.so \
    $(shared-thread-library)
 +$(objpfx)tst-resolv-invalid-cname: $(objpfx)libresolv.so \
++  $(shared-thread-library)
++$(objpfx)tst-resolv-invalid-ptr: $(objpfx)libresolv.so \
 +  $(shared-thread-library)
  $(objpfx)tst-resolv-noaaaa: $(objpfx)libresolv.so $(shared-thread-library)
 +$(objpfx)tst-resolv-noaaaa-vc: $(objpfx)libresolv.so $(shared-thread-library)
@@ -6798,7 +7855,7 @@ index 0000000000..9a47d8e97a
 +  return *a == 0 && *b == 0;
 +}
 diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
-index 544cffbecd..227734da5c 100644
+index 544cffbecd..7053f212ae 100644
 --- a/resolv/nss_dns/dns-host.c
 +++ b/resolv/nss_dns/dns-host.c
 @@ -69,6 +69,7 @@
@@ -7522,7 +8579,7 @@ index 544cffbecd..227734da5c 100644
 +  unsigned char name_buffer[NS_MAXCDNAME];
  
 -      if (__glibc_unlikely (class != C_IN))
-+  while (ancount > 0)
++  for (; ancount > 0; --ancount)
 +    {
 +      struct ns_rr_wire rr;
 +      if (!__ns_rr_cursor_next (&c, &rr))
@@ -7647,7 +8704,7 @@ index 544cffbecd..227734da5c 100644
 +	  char hname[MAXHOSTNAMELEN + 1];
 +	  if (__ns_name_unpack (c.begin, c.end, rr.rdata,
 +				name_buffer, sizeof (name_buffer)) < 0
-+	      || !__res_binary_hnok (expected_name)
++	      || !__res_binary_hnok (name_buffer)
 +	      || __ns_name_ntop (name_buffer, hname, sizeof (hname)) < 0)
  	    {
 -	      cp += n;
@@ -8245,6 +9302,21 @@ index 544cffbecd..227734da5c 100644
 +				   abuf, &pat, errnop, h_errnop, ttlp, true);
    return status;
  }
+diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
+index 09cd917444..3458bd4615 100644
+--- a/resolv/nss_dns/dns-network.c
++++ b/resolv/nss_dns/dns-network.c
+@@ -207,6 +207,10 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
+       sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2],
+ 	       net_bytes[1], net_bytes[0]);
+       break;
++    default:
++      /* Default network (net is originally zero).  */
++      strcpy (qbuf, "0.0.0.0.in-addr.arpa");
++      break;
+     }
+ 
+   net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
 diff --git a/resolv/res-name-checking.c b/resolv/res-name-checking.c
 index 07a412d8ff..213edceaf3 100644
 --- a/resolv/res-name-checking.c
@@ -9416,6 +10488,174 @@ index 0000000000..6299e89837
 +}
 +
 +#include <support/test-driver.c>
+diff --git a/resolv/tst-resolv-dns-section.c b/resolv/tst-resolv-dns-section.c
+new file mode 100644
+index 0000000000..1171baef51
+--- /dev/null
++++ b/resolv/tst-resolv-dns-section.c
+@@ -0,0 +1,162 @@
++/* Test handling of invalid section transitions (bug 34014).
++   Copyright (C) 2022-2026 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <array_length.h>
++#include <errno.h>
++#include <netdb.h>
++#include <resolv.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/format_nss.h>
++#include <support/resolv_test.h>
++#include <support/support.h>
++
++/* Name of test, and the second section type.  */
++struct item {
++  const char *test;
++  int ns_section;
++};
++
++static const struct item test_items[] =
++  {
++    { "Test crossing from ns_s_an to ns_s_ar.", ns_s_ar },
++    { "Test crossing from ns_s_an to ns_s_an.", ns_s_ns },
++
++    { NULL, 0 },
++  };
++
++/* The response is designed to contain the following:
++   - An Answer section with one T_PTR record that is skipped.
++   - A second section with a semantically invalid T_PTR record.
++   The original defect is that the response parsing would cross
++   section boundaries and handle the additional section T_PTR
++   as if it were an answer.  A conforming implementation would
++   stop as soon as it reaches the end of the section.  */
++static void
++response (const struct resolv_response_context *ctx,
++          struct resolv_response_builder *b,
++          const char *qname, uint16_t qclass, uint16_t qtype)
++{
++  TEST_COMPARE (qclass, C_IN);
++
++  /* We only test PTR.  */
++  TEST_COMPARE (qtype, T_PTR);
++
++  unsigned int count;
++  char *tail = NULL;
++
++  if (strstr (qname, "in-addr.arpa") != NULL
++      && sscanf (qname, "%u.%ms", &count, &tail) == 2)
++    TEST_COMPARE_STRING (tail, "0.168.192.in-addr.arpa");
++  else if (sscanf (qname, "%x.%ms", &count, &tail) == 2)
++    {
++    TEST_COMPARE_STRING (tail, "\
++0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
++    }
++  else
++    FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
++  free (tail);
++
++  /* We have a bounded number of possible tests.  */
++  TEST_VERIFY (count >= 0);
++  TEST_VERIFY (count <= 15);
++
++  struct resolv_response_flags flags = {};
++  resolv_response_init (b, flags);
++  resolv_response_add_question (b, qname, qclass, qtype);
++  resolv_response_section (b, ns_s_an);
++
++  /* Actual answer record, but the wrong name (skipped).  */
++  resolv_response_open_record (b, "1.0.0.10.in-addr.arpa", qclass, qtype, 60);
++
++  /* Record the answer.  */
++  resolv_response_add_name (b, "test.ptr.example.net");
++  resolv_response_close_record (b);
++
++  /* Add a second section to test section boundary crossing.  */
++  resolv_response_section (b, test_items[count].ns_section);
++  /* Semantically incorrect, but hide a T_PTR entry.  */
++  resolv_response_open_record (b, qname, qclass, qtype, 60);
++  resolv_response_add_name (b, "wrong.ptr.example.net");
++  resolv_response_close_record (b);
++}
++
++
++/* Perform one check using a reverse lookup.  */
++static void
++check_reverse (int af, int count)
++{
++  TEST_VERIFY (af == AF_INET || af == AF_INET6);
++  TEST_VERIFY (count < array_length (test_items));
++
++  char addr[sizeof (struct in6_addr)] = { 0 };
++  socklen_t addrlen;
++  if (af == AF_INET)
++    {
++      addr[0] = (char) 192;
++      addr[1] = (char) 168;
++      addr[2] = (char) 0;
++      addr[3] = (char) count;
++      addrlen = 4;
++    }
++  else
++    {
++      addr[0] = 0x20;
++      addr[1] = 0x01;
++      addr[2] = 0x0d;
++      addr[3] = 0xb8;
++      addr[4] = addr[5] = addr[6] = addr[7] = 0x0;
++      addr[8] = addr[9] = addr[10] = addr[11] = 0x0;
++      addr[12] = 0x0;
++      addr[13] = 0x0;
++      addr[14] = 0x0;
++      addr[15] = count;
++      addrlen = 16;
++    }
++
++  h_errno = 0;
++  struct hostent *answer = gethostbyaddr (addr, addrlen, af);
++  TEST_VERIFY (answer == NULL);
++  TEST_VERIFY (h_errno == NO_RECOVERY);
++  if (answer != NULL)
++    printf ("error: unexpected success: %s\n",
++	    support_format_hostent (answer));
++}
++
++static int
++do_test (void)
++{
++  struct resolv_test *obj = resolv_test_start
++    ((struct resolv_redirect_config)
++     {
++       .response_callback = response
++     });
++
++  for (int i = 0; test_items[i].test != NULL; i++)
++    {
++      check_reverse (AF_INET, i);
++      check_reverse (AF_INET6, i);
++    }
++
++  resolv_test_end (obj);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
 diff --git a/resolv/tst-resolv-invalid-cname.c b/resolv/tst-resolv-invalid-cname.c
 new file mode 100644
 index 0000000000..63dac90e02
@@ -9828,6 +11068,267 @@ index 0000000000..63dac90e02
 +}
 +
 +#include <support/test-driver.c>
+diff --git a/resolv/tst-resolv-invalid-ptr.c b/resolv/tst-resolv-invalid-ptr.c
+new file mode 100644
+index 0000000000..0c802ab967
+--- /dev/null
++++ b/resolv/tst-resolv-invalid-ptr.c
+@@ -0,0 +1,255 @@
++/* Test handling of invalid T_PTR results (bug 34015).
++   Copyright (C) 2022-2026 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
++   <https://www.gnu.org/licenses/>.  */
++
++#include <array_length.h>
++#include <errno.h>
++#include <netdb.h>
++#include <resolv.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/format_nss.h>
++#include <support/resolv_test.h>
++#include <support/support.h>
++
++/* Name of test, the answer, the expected error return, and if we
++   expect the call to fail.  */
++struct item {
++  const char *test;
++  const char *answer;
++  int expected;
++  bool fail;
++};
++
++static const struct item test_items[] =
++  {
++    /* Test for invalid characters.  */
++    { "Invalid use of \"|\"",
++      "test.|.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"&\"",
++      "test.&.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \";\"",
++      "test.;.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"<\"",
++      "test.<.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \">\"",
++      "test.>.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"(\"",
++      "test.(.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \")\"",
++      "test.).ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"$\"",
++      "test.$.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"`\"",
++      "test.`.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"\\\"",
++      "test.\\.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"\'\"",
++      "test.'.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"\"\"",
++      "test.\".ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \" \"",
++      "test. .ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"\\t\"",
++      "test.\t.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"\\n\"",
++      "test.\n.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"\\r\"",
++      "test.\r.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"*\"",
++      "test.*.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"?\"",
++      "test.?.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"[\"",
++      "test.[.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"]\"",
++      "test.].ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \",\"",
++      "test.,.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"~\"",
++      "test.~.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \":\"",
++      "test.:.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"!\"",
++      "test.!.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"@\"",
++      "[email protected]", NO_RECOVERY, true },
++    { "Invalid use of \"#\"",
++      "test.#.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"%\"",
++      "test.%%.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of \"^\"",
++      "test.^.ptr.example", NO_RECOVERY, true },
++
++    /* Test for invalid UTF-8 characters (2-byte, 4-byte, 6-byte).  */
++    { "Invalid use of UTF-8 (2-byte, U+00C0-U+00C2)",
++      "ÁÂÃ.test.ptr.example", NO_RECOVERY, true },
++    { "Invalid use of UTF-8 (4-byte, U+0750-U+0752)",
++      "ݐݑݒ.test.ptr.example", NO_RECOVERY, true },
++     { "Invalid use of UTF-8 (6-byte, U+0904-U+0906)",
++      "ऄअआ.test.ptr.example", NO_RECOVERY, true },
++
++    /* Test for "-" which may be valid depending on position.  */
++    { "Invalid leading \"-\"",
++      "-test.ptr.example", NO_RECOVERY, true },
++    { "Valid trailing \"-\"",
++      "test-.ptr.example", 0, false },
++    { "Valid mid-label use of \"-\"",
++      "te-st.ptr.example", 0, false },
++
++    /* Test for "_" which is always valid in any position.  */
++    { "Valid leading use of \"_\"",
++      "_test.ptr.example", 0, false },
++    { "Valid mid-label use of \"_\"",
++      "te_st.ptr.example", 0, false },
++    { "Valid trailing use of \"_\"",
++      "test_.ptr.example", 0, false },
++
++    /* Sanity test the broader set [A-Za-z0-9_-] of valid characters.  */
++    { "Valid \"[A-Z]\"",
++      "test.ABCDEFGHIJKLMNOPQRSTUVWXYZ.ptr.example", 0, false },
++    { "Valid \"[a-z]\"",
++      "test.abcdefghijklmnopqrstuvwxyz.ptr.example", 0, false },
++    { "Valid \"[0-9]\"",
++      "test.0123456789.ptr.example", 0, false },
++    { "Valid mixed use of \"[A-Za-z0-9_-]\"",
++      "test.012abcABZ_-.ptr.example", 0, false },
++  };
++
++static void
++response (const struct resolv_response_context *ctx,
++          struct resolv_response_builder *b,
++          const char *qname, uint16_t qclass, uint16_t qtype)
++{
++  TEST_COMPARE (qclass, C_IN);
++
++  /* We only test PTR.  */
++  TEST_COMPARE (qtype, T_PTR);
++
++  unsigned int count, count1;
++  char *tail = NULL;
++
++  /* The test implementation can handle up to 255 tests.  */
++  if (strstr (qname, "in-addr.arpa") != NULL
++      && sscanf (qname, "%u.%ms", &count, &tail) == 2)
++    TEST_COMPARE_STRING (tail, "0.168.192.in-addr.arpa");
++  else if (sscanf (qname, "%x.%x.%ms", &count, &count1, &tail) == 3)
++    {
++      TEST_COMPARE_STRING (tail, "\
++0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa");
++      count |= count1 << 4;
++    }
++  else
++    FAIL_EXIT1 ("invalid QNAME: %s\n", qname);
++  free (tail);
++
++  /* Cross check. Count has a fixed bound (soft limit).  */
++  TEST_VERIFY (count >= 0 && count <= 255);
++
++  /* We have a fixed number of tests (hard limit).  */
++  TEST_VERIFY_EXIT (count < array_length (test_items));
++
++  struct resolv_response_flags flags = {};
++  resolv_response_init (b, flags);
++  resolv_response_add_question (b, qname, qclass, qtype);
++  resolv_response_section (b, ns_s_an);
++
++  /* Actual answer record.  */
++  resolv_response_open_record (b, qname, qclass, qtype, 60);
++
++  /* Record the answer.  */
++  resolv_response_add_name (b, test_items[count].answer);
++  resolv_response_close_record (b);
++}
++
++/* Perform one check using a reverse lookup.  */
++static void
++check_reverse (int af, int count)
++{
++  TEST_VERIFY (af == AF_INET || af == AF_INET6);
++  TEST_VERIFY_EXIT (count < array_length (test_items));
++
++  /* Generate an address to query for each test.  */
++  char addr[sizeof (struct in6_addr)] = { 0 };
++  socklen_t addrlen;
++  if (af == AF_INET)
++    {
++      addr[0] = (char) 192;
++      addr[1] = (char) 168;
++      addr[2] = (char) 0;
++      addr[3] = (char) count;
++      addrlen = 4;
++    }
++  else
++    {
++      addr[0] = 0x20;
++      addr[1] = 0x01;
++      addr[2] = 0x0d;
++      addr[3] = 0xb8;
++      addr[4] = addr[5] = addr[6] = addr[7] = 0x0;
++      addr[8] = addr[9] = addr[10] = addr[11] = 0x0;
++      addr[12] = 0x0;
++      addr[13] = 0x0;
++      addr[14] = 0x0;
++      addr[15] = (char) count;
++      addrlen = 16;
++    }
++
++  h_errno = 0;
++  struct hostent *answer = gethostbyaddr (addr, addrlen, af);
++
++  /* Verify h_errno is as expected.  */
++  TEST_COMPARE (h_errno, test_items[count].expected);
++  if (h_errno != test_items[count].expected)
++    /* And print more information if it's not.  */
++    printf ("INFO: %s\n", test_items[count].test);
++
++  if (test_items[count].fail)
++    {
++      /* We expected a failure so verify answer is NULL.  */
++      TEST_VERIFY (answer == NULL);
++      /* If it's not NULL we should print out what we received.  */
++      if (answer != NULL)
++        printf ("error: unexpected success: %s\n",
++		support_format_hostent (answer));
++    }
++  else
++    /* We don't expect a failure so answer must be valid.  */
++    TEST_COMPARE_STRING (answer->h_name, test_items[count].answer);
++}
++
++static int
++do_test (void)
++{
++  struct resolv_test *obj = resolv_test_start
++    ((struct resolv_redirect_config)
++     {
++       .response_callback = response
++     });
++
++  for (int i = 0; i < array_length (test_items); i++)
++    {
++      check_reverse (AF_INET, i);
++      check_reverse (AF_INET6, i);
++    }
++  resolv_test_end (obj);
++
++  return 0;
++}
++
++#include <support/test-driver.c>
 diff --git a/resolv/tst-resolv-maybe_insert_sig.h b/resolv/tst-resolv-maybe_insert_sig.h
 new file mode 100644
 index 0000000000..05725225af
@@ -9866,6 +11367,30 @@ index 0000000000..05725225af
 +  resolv_response_add_data (b, "", 1);
 +  resolv_response_close_record (b);
 +}
+diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c
+index 956f847db7..f1f11613ac 100644
+--- a/resolv/tst-resolv-network.c
++++ b/resolv/tst-resolv-network.c
+@@ -46,6 +46,9 @@ handle_code (const struct resolv_response_context *ctx,
+ {
+   switch (code)
+     {
++    case 0:
++      send_ptr (b, qname, qclass, qtype, "0.in-addr.arpa");
++      break;
+     case 1:
+       send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa");
+       break;
+@@ -265,6 +268,9 @@ do_test (void)
+                 "error: TRY_AGAIN\n");
+ 
+   /* Lookup by address, success cases.  */
++  check_reverse (0,
++                 "name: 0.in-addr.arpa\n"
++                 "net: 0x00000000\n");
+   check_reverse (1,
+                  "name: 1.in-addr.arpa\n"
+                  "net: 0x00000001\n");
 diff --git a/resolv/tst-resolv-noaaaa-vc.c b/resolv/tst-resolv-noaaaa-vc.c
 new file mode 100644
 index 0000000000..9f5aebd99f
@@ -15420,6 +16945,81 @@ index 6a422713bd..659c6f16da 100644
  	@ save the entry point in another register\n\
  	mov	r6, r0\n\
  	@ get the original arg count\n\
+diff --git a/sysdeps/arm/find_exidx.c b/sysdeps/arm/find_exidx.c
+index aab06d25f6..0236b1f4ca 100644
+--- a/sysdeps/arm/find_exidx.c
++++ b/sysdeps/arm/find_exidx.c
+@@ -15,65 +15,17 @@
+    License along with the GNU C Library.  If not, see
+    <https://www.gnu.org/licenses/>.  */
+ 
++#include <ldsodefs.h>
+ #include <link.h>
+-#include <unwind.h>
+-
+-struct unw_eh_callback_data
+-{
+-  _Unwind_Ptr pc;
+-  _Unwind_Ptr exidx_start;
+-  int exidx_len;
+-};
+-
+-
+-/* Callback to determins if the PC lies within an object, and remember the
+-   location of the exception index table if it does.  */
+-
+-static int
+-find_exidx_callback (struct dl_phdr_info * info, size_t size, void * ptr)
+-{
+-  struct unw_eh_callback_data * data;
+-  const ElfW(Phdr) *phdr;
+-  int i;
+-  int match;
+-  _Unwind_Ptr load_base;
+-
+-  data = (struct unw_eh_callback_data *) ptr;
+-  load_base = info->dlpi_addr;
+-  phdr = info->dlpi_phdr;
+-
+-  match = 0;
+-  for (i = info->dlpi_phnum; i > 0; i--, phdr++)
+-    {
+-      if (phdr->p_type == PT_LOAD)
+-        {
+-          _Unwind_Ptr vaddr = phdr->p_vaddr + load_base;
+-          if (data->pc >= vaddr && data->pc < vaddr + phdr->p_memsz)
+-            match = 1;
+-        }
+-      else if (phdr->p_type == PT_ARM_EXIDX)
+-	{
+-	  data->exidx_start = (_Unwind_Ptr) (phdr->p_vaddr + load_base);
+-	  data->exidx_len = phdr->p_memsz;
+-	}
+-    }
+-
+-  return match;
+-}
+-
+ 
+ /* Find the exception index table containing PC.  */
+ 
+ _Unwind_Ptr
+ __gnu_Unwind_Find_exidx (_Unwind_Ptr pc, int * pcount)
+ {
+-  struct unw_eh_callback_data data;
+-
+-  data.pc = pc;
+-  data.exidx_start = 0;
+-  if (__dl_iterate_phdr (find_exidx_callback, &data) <= 0)
++  struct dl_find_object data;
++  if (GLRO(dl_find_object) ((void *) pc, &data) < 0)
+     return 0;
+-
+-  *pcount = data.exidx_len / 8;
+-  return data.exidx_start;
++  *pcount = data.dlfo_eh_count;
++  return (_Unwind_Ptr) data.dlfo_eh_frame;
+ }
 diff --git a/sysdeps/arm/utmp-size.h b/sysdeps/arm/utmp-size.h
 new file mode 100644
 index 0000000000..8f21ebe1b6
@@ -16373,6 +17973,19 @@ index bb0ccd0811..3868bcc2f7 100644
  
  /* The PLT uses Elf64_Rela relocs.  */
  #define elf_machine_relplt elf_machine_rela
+diff --git a/sysdeps/powerpc/powerpc64/le/power10/strlen.S b/sysdeps/powerpc/powerpc64/le/power10/strlen.S
+index 5c42f78de9..b9c7f511cf 100644
+--- a/sysdeps/powerpc/powerpc64/le/power10/strlen.S
++++ b/sysdeps/powerpc/powerpc64/le/power10/strlen.S
+@@ -31,7 +31,7 @@
+ #  define FUNCNAME RAWMEMCHR
+ # endif
+ # define MCOUNT_NARGS 2
+-# define VREG_ZERO v20
++# define VREG_ZERO v17
+ # define OFF_START_LOOP 256
+ # define RAWMEMCHR_SUBTRACT_VECTORS \
+ 	vsububm   v4,v4,v18;	    \
 diff --git a/sysdeps/powerpc/utmp-size.h b/sysdeps/powerpc/utmp-size.h
 new file mode 100644
 index 0000000000..8f21ebe1b6
@@ -19742,6 +21355,42 @@ index 0000000000..8f21ebe1b6
 @@ -0,0 +1,2 @@
 +#define UTMP_SIZE 384
 +#define LASTLOG_SIZE 292
+diff --git a/sysdeps/x86_64/Makefile b/sysdeps/x86_64/Makefile
+index c19bef2dec..f173c5ef4a 100644
+--- a/sysdeps/x86_64/Makefile
++++ b/sysdeps/x86_64/Makefile
+@@ -190,6 +190,15 @@ endif
+ 
+ tests-internal += tst-x86-64-tls-1
+ 
++tests-special += $(objpfx)check-dt-x86-64-plt.out
++
++$(objpfx)check-dt-x86-64-plt.out: $(common-objpfx)libc.so
++       LC_ALL=C $(READELF) -V -W $< \
++               | sed -ne '/.gnu.version_d/, /.gnu.version_r/ p' \
++               | grep GLIBC_ABI_DT_X86_64_PLT > $@; \
++       $(evaluate-test)
++generated += check-dt-x86-64-plt.out
++
+ endif # $(subdir) == elf
+ 
+ ifeq ($(subdir),csu)
+diff --git a/sysdeps/x86_64/Versions b/sysdeps/x86_64/Versions
+index e94758b236..6a989ad3b3 100644
+--- a/sysdeps/x86_64/Versions
++++ b/sysdeps/x86_64/Versions
+@@ -5,6 +5,11 @@ libc {
+   GLIBC_2.13 {
+     __fentry__;
+   }
++  GLIBC_ABI_DT_X86_64_PLT {
++    # This symbol is used only for empty version map and will be removed
++    # by scripts/versions.awk.
++    __placeholder_only_for_empty_version_map;
++  }
+ }
+ libm {
+   GLIBC_2.1 {
 diff --git a/sysdeps/x86_64/dl-tls.c b/sysdeps/x86_64/dl-tls.c
 index 24a6e643b0..86517573dc 100644
 --- a/sysdeps/x86_64/dl-tls.c
@@ -20409,6 +22058,19 @@ index 68646ef199..7622af259c 100644
        && X86_ISA_CPU_FEATURES_ARCH_P (cpu_features,
  				      AVX_Fast_Unaligned_Load, ))
      {
+diff --git a/sysdeps/x86_64/multiarch/ifunc-wmemset.h b/sysdeps/x86_64/multiarch/ifunc-wmemset.h
+index 3810c719c6..9e58bc00b5 100644
+--- a/sysdeps/x86_64/multiarch/ifunc-wmemset.h
++++ b/sysdeps/x86_64/multiarch/ifunc-wmemset.h
+@@ -35,7 +35,7 @@ IFUNC_SELECTOR (void)
+ 
+   if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX2)
+       && X86_ISA_CPU_FEATURES_ARCH_P (cpu_features,
+-				      AVX_Fast_Unaligned_Load, !))
++				      AVX_Fast_Unaligned_Load,))
+     {
+       if (X86_ISA_CPU_FEATURE_USABLE_P (cpu_features, AVX512VL))
+ 	{
 diff --git a/sysdeps/x86_64/multiarch/memcmp-sse2.S b/sysdeps/x86_64/multiarch/memcmp-sse2.S
 index afd450d020..51bc9344f0 100644
 --- a/sysdeps/x86_64/multiarch/memcmp-sse2.S
diff --git a/debian/patches/series b/debian/patches/series
index 153a5d9d..7217d7dc 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -21,6 +21,8 @@ alpha/local-string-functions.diff
 alpha/submitted-fts64.diff
 alpha/submitted-makecontext.diff
 
+amd64/local-revert-x86-64-add-GLIBC_ABI_DT_X86_64_PLT-version.diff
+
 arm/local-sigaction.diff
 arm/unsubmitted-ldso-multilib.diff
 arm/local-arm-futex.diff