[PATCH v2] libio: Fix CVE-2026-18374 - fopen heap buffer overflow with empty ccs=

=?ks_c_5601-1987?B?vNW1v7HVL1Byb2Nlc3MgJiBJbmZyYSBMYWIoU1IpL7vvvLrA/MDa?= <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <[email protected]>
Hi all,

My v1 of this patch did not apply cleanly -- most likely my mail client
damaged the inline diff (line wrapping / whitespace), so the automated
apply check failed. I'm resending a clean version generated with
git format-patch on current master and attached to this mail to avoid any
whitespace issues. Apologies for the noise.

The patch has been regenerated on top of current master
(655656fcc6 "manual: Fix some typos in the Low-Level Input/Output
chapter") and verified to apply cleanly with both "git apply --check" and
"git am".

Changes since v1:
  - No functional changes. v2 is the same fix as v1, regenerated on
    current master as a clean, applyable patch.

Summary
-------
CVE-2026-18374: heap buffer overflow in fopen() with an empty ,ccs=
parameter (GLIBC-SA-2026-0015, CVSS 4.9,
AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L).

When fopen("file", "r,ccs=") is called with an empty charset
specification, endp - (cs + 5) == 0, so only 3 bytes are allocated for
the ccs buffer. This patch rejects an empty ccs= string with EINVAL
before allocation, and extracts the length into a size_t (ccs_len) for
clarity. A regression test is added to libio/tst-fopenloc.c.

The patch is attached as:
  0001-CVE-2026-18374-v2.patch

Thanks,
Dongkyun Son
0001-CVE-2026-18374-v2.patch (application/octet-stream, 2.9 KB)
From 915f9c838d923e75562f96baff6aff45312acd92 Mon Sep 17 00:00:00 2001
From: Dongkyun Son <[email protected]>
Date: Fri, 28 Aug 2026 16:03:53 +0900
Subject: [PATCH v2] libio: Fix CVE-2026-18374 - fopen heap buffer overflow
 with empty ccs=

Passing an empty string to the ,ccs= parameter in fopen() could cause a
heap buffer overflow. The vulnerable code allocated a buffer of size 3
bytes when endp - (cs + 5) = 0 (empty ccs value), which could be
insufficient for the conversion processing.

This patch adds validation to reject empty ccs= strings with EINVAL,
preventing the buffer overflow. Additionally, the ccs_len variable is
extracted to improve code clarity and safety.

CVE-2026-18374 - CVSS 4.9 (AV:L/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L)
Reported-by: AISLE in partnership with Red Hat
Signed-off-by: Dongkyun Son <[email protected]>
---
 libio/fileops.c      | 14 ++++++++++++--
 libio/tst-fopenloc.c | 26 ++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/libio/fileops.c b/libio/fileops.c
index 9348d7c3a1..2137d0ee1f 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -342,7 +342,17 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode,
 	  struct gconv_fcts fcts;
 	  struct _IO_codecvt *cc;
 	  char *endp = __strchrnul (cs + 5, ',');
-	  char *ccs = malloc (endp - (cs + 5) + 3);
+	  size_t ccs_len = endp - (cs + 5);
+
+	  /* Reject empty ccs= string to prevent heap buffer overflow.  */
+	  if (ccs_len == 0)
+	    {
+	      (void) _IO_file_close_it (fp);
+	      __set_errno (EINVAL);
+	      return NULL;
+	    }
+
+	  char *ccs = malloc (ccs_len + 3);
 
 	  if (ccs == NULL)
 	    {
@@ -352,7 +362,7 @@ _IO_new_file_fopen (FILE *fp, const char *filename, const char *mode,
 	      return NULL;
 	    }
 
-	  *((char *) __mempcpy (ccs, cs + 5, endp - (cs + 5))) = '\0';
+	  *((char *) __mempcpy (ccs, cs + 5, ccs_len)) = '\0';
 	  strip (ccs, ccs);
 
 	  if (__wcsmbs_named_conv (&fcts, ccs[2] == '\0'
diff --git a/libio/tst-fopenloc.c b/libio/tst-fopenloc.c
index ea3f7b5265..2d2889ae08 100644
--- a/libio/tst-fopenloc.c
+++ b/libio/tst-fopenloc.c
@@ -85,6 +85,31 @@ do_bz18906 (void)
   return EXIT_SUCCESS;
 }
 
+static int
+do_cve_2026_18374 (void)
+{
+  /* CVE-2026-18374 -- reject empty ccs= to prevent heap buffer overflow.  */
+
+  const char *ccs = "r,ccs=";
+  FILE *fp = fopen (inputfile, ccs);
+
+  if (fp != NULL)
+    {
+      printf ("fopen with empty ccs= should have failed but succeeded\n");
+      fclose (fp);
+      return 1;
+    }
+
+  /* Check that errno is set to EINVAL for invalid ccs parameter.  */
+  if (errno != EINVAL)
+    {
+      printf ("expected EINVAL, got %d\n", errno);
+      return 1;
+    }
+
+  return 0;
+}
+
 static int
 do_test (void)
 {
@@ -110,6 +135,7 @@ do_test (void)
 
   TEST_COMPARE (do_bz17916 (), 0);
   TEST_COMPARE (do_bz18906 (), 0);
+  TEST_COMPARE (do_cve_2026_18374 (), 0);
 
   return EXIT_SUCCESS;
 }
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.