[PATCH] nss: use C locale for parsing nsswitch.conf (bug 33519)

Andreas Schwab schwab@suse.de
Wed Oct 8 11:29:42 GMT 2025


The keywords in nsswitch.conf are ASCII-only, but some locales map ASCII
charactes to non-ASCII characters in case conversion.
---
 nss/Makefile                                  |  6 +++
 nss/nss_action_parse.c                        | 32 ++++++++------
 nss/tst-nss-action-parse.c                    | 42 +++++++++++++++++++
 nss/tst-nss-action-parse.root/etc/group       |  1 +
 .../etc/nsswitch.conf                         |  1 +
 5 files changed, 70 insertions(+), 12 deletions(-)
 create mode 100644 nss/tst-nss-action-parse.c
 create mode 100644 nss/tst-nss-action-parse.root/etc/group
 create mode 100644 nss/tst-nss-action-parse.root/etc/nsswitch.conf

diff --git a/nss/Makefile b/nss/Makefile
index 1991b7482a..96d9295778 100644
--- a/nss/Makefile
+++ b/nss/Makefile
@@ -356,6 +356,7 @@ tests-container := \
   tst-nss-gai-actions \
   tst-nss-gai-hv2-canonname \
   tst-nss-test3 \
+  tst-nss-action-parse \
   tst-reload1 \
   tst-reload2 \
   # tests-container
@@ -444,6 +445,9 @@ generated += mtrace-tst-nss-gai-hv2-canonname.out \
 
 include ../Rules
 
+LOCALES := tr_TR.UTF-8
+include ../gen-locales.mk
+
 ifeq (yes,$(have-selinux))
 LDLIBS-makedb		:= -lselinux
 endif
@@ -521,6 +525,8 @@ $(objpfx)mtrace-tst-nss-gai-hv2-canonname.out: \
 	$(objpfx)tst-nss-gai-hv2-canonname.mtrace; } > $@; \
 	$(evaluate-test)
 
+$(objpfx)tst-nss-action-parse.out: $(gen-locales)
+
 # Disable DT_RUNPATH on NSS tests so that the glibc internal NSS
 # functions can load testing NSS modules via DT_RPATH.
 LDFLAGS-tst-nss-test1 = -Wl,--disable-new-dtags
diff --git a/nss/nss_action_parse.c b/nss/nss_action_parse.c
index ee3aadf312..cf55b7036b 100644
--- a/nss/nss_action_parse.c
+++ b/nss/nss_action_parse.c
@@ -48,7 +48,8 @@ nss_action_parse (const char *line, struct action_list *result)
 
       /* Read <source> identifier.  */
       const char *name = line;
-      while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[')
+      while (line[0] != '\0' && !__isspace_l (line[0], _nl_C_locobj_ptr)
+	     && line[0] != '[')
         ++line;
       if (name == line)
         return true;
@@ -88,25 +89,29 @@ nss_action_parse (const char *line, struct action_list *result)
 
               /* Read status name.  */
               name = line;
-              while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
-                     && line[0] != ']')
+              while (line[0] != '\0' && !__isspace_l (line[0], _nl_C_locobj_ptr)
+		     && line[0] != '=' && line[0] != ']')
                 ++line;
 
               /* Compare with known statuses.  */
               if (line - name == 7)
                 {
-                  if (__strncasecmp (name, "SUCCESS", 7) == 0)
+                  if (__strncasecmp_l (name, "SUCCESS", 7,
+				       _nl_C_locobj_ptr) == 0)
                     status = NSS_STATUS_SUCCESS;
-                  else if (__strncasecmp (name, "UNAVAIL", 7) == 0)
+                  else if (__strncasecmp_l (name, "UNAVAIL", 7,
+					    _nl_C_locobj_ptr) == 0)
                     status = NSS_STATUS_UNAVAIL;
                   else
                     return false;
                 }
               else if (line - name == 8)
                 {
-                  if (__strncasecmp (name, "NOTFOUND", 8) == 0)
+                  if (__strncasecmp_l (name, "NOTFOUND", 8,
+				       _nl_C_locobj_ptr) == 0)
                     status = NSS_STATUS_NOTFOUND;
-                  else if (__strncasecmp (name, "TRYAGAIN", 8) == 0)
+                  else if (__strncasecmp_l (name, "TRYAGAIN", 8,
+					    _nl_C_locobj_ptr) == 0)
                     status = NSS_STATUS_TRYAGAIN;
                   else
                     return false;
@@ -122,17 +127,20 @@ nss_action_parse (const char *line, struct action_list *result)
 	      ++line;
 	      SKIP_WS ();
               name = line;
-              while (line[0] != '\0' && !isspace (line[0]) && line[0] != '='
-                     && line[0] != ']')
+              while (line[0] != '\0' && !__isspace_l (line[0], _nl_C_locobj_ptr)
+		     && line[0] != '=' && line[0] != ']')
                 ++line;
 
-              if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0)
+              if (line - name == 6
+		  && __strncasecmp_l (name, "RETURN", 6, _nl_C_locobj_ptr) == 0)
                 action = NSS_ACTION_RETURN;
               else if (line - name == 8
-                       && __strncasecmp (name, "CONTINUE", 8) == 0)
+                       && __strncasecmp_l (name, "CONTINUE", 8,
+					   _nl_C_locobj_ptr) == 0)
                 action = NSS_ACTION_CONTINUE;
               else if (line - name == 5
-                       && __strncasecmp (name, "MERGE", 5) == 0)
+                       && __strncasecmp_l (name, "MERGE", 5,
+					   _nl_C_locobj_ptr) == 0)
                 action = NSS_ACTION_MERGE;
               else
                 return false;
diff --git a/nss/tst-nss-action-parse.c b/nss/tst-nss-action-parse.c
new file mode 100644
index 0000000000..8c4a71085e
--- /dev/null
+++ b/nss/tst-nss-action-parse.c
@@ -0,0 +1,42 @@
+/* Test that the nsswitch.conf parser is locale agnostic.
+   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 <locale.h>
+#include <grp.h>
+
+#include <support/support.h>
+#include <support/check.h>
+
+/* Test that the nsswitch.conf parser works correctly in a locale that
+   maps ASCII characters to non-ASCII characters in case conversion.
+   Bug #33519  */
+
+static int
+do_test (void)
+{
+  xsetlocale (LC_ALL, "tr_TR.UTF-8");
+
+  /* Trigger parsing of nsswitch.conf.  If that fails then the use of any
+     NSS function will return an error.  */
+  struct group *grp = getgrgid (0);
+  TEST_VERIFY (grp != NULL);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/nss/tst-nss-action-parse.root/etc/group b/nss/tst-nss-action-parse.root/etc/group
new file mode 100644
index 0000000000..1dbf9013ee
--- /dev/null
+++ b/nss/tst-nss-action-parse.root/etc/group
@@ -0,0 +1 @@
+root:x:0:
diff --git a/nss/tst-nss-action-parse.root/etc/nsswitch.conf b/nss/tst-nss-action-parse.root/etc/nsswitch.conf
new file mode 100644
index 0000000000..4f5151f625
--- /dev/null
+++ b/nss/tst-nss-action-parse.root/etc/nsswitch.conf
@@ -0,0 +1 @@
+group: files [unavail=return]
-- 
2.51.0


-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."


More information about the Libc-alpha mailing list