]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
nss: use C locale for parsing nsswitch.conf (bug 33519)
authorAndreas Schwab <schwab@suse.de>
Wed, 8 Oct 2025 10:26:18 +0000 (12:26 +0200)
committerAndreas Schwab <schwab@suse.de>
Wed, 8 Oct 2025 12:34:24 +0000 (14:34 +0200)
The keywords in nsswitch.conf are ASCII-only, but some locales map ASCII
characters to non-ASCII characters in case conversion.

nss/Makefile
nss/nss_action_parse.c
nss/tst-nss-action-parse.c [new file with mode: 0644]
nss/tst-nss-action-parse.root/etc/group [new file with mode: 0644]
nss/tst-nss-action-parse.root/etc/nsswitch.conf [new file with mode: 0644]

index 1991b7482a93158718bc64cd01328a1b4e495c23..96d92957789b5da4f9d556db7ea27cd17bc4245e 100644 (file)
@@ -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
index ee3aadf31277aa77f6aa8d87f1f99e53c74528c7..cf55b7036bb170b2f6d5220a4c38504d478e5020 100644 (file)
@@ -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 (file)
index 0000000..8c4a710
--- /dev/null
@@ -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 (file)
index 0000000..1dbf901
--- /dev/null
@@ -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 (file)
index 0000000..4f5151f
--- /dev/null
@@ -0,0 +1 @@
+group: files [unavail=return]