bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

canonicalize: Add support for UNC file names on native Windows


From: Bruno Haible
Subject: canonicalize: Add support for UNC file names on native Windows
Date: Mon, 21 Sep 2020 00:49:51 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-189-generic; KDE/5.18.0; x86_64; ; )

Through the 'supersede' module, gettext now uses the 'canonicalize' module.
Vaclav Slavik reported in <https://savannah.gnu.org/bugs/?59079>:

  "msgfmt ... to unmounted shared folders on Windows via UNC paths
   (e.g. \\localhost\sharedfolder) fails. I got multiple reports of this
   pretty quickly, so it's not as obscure an edge case as one could be
   excused to think.

   This is because fopen_supersede() uses canonicalize_filename_mode() which
   doesn't handle this situation correctly. While it has code in place to
   recognize leading double-slash as being different from single-slash, and
   knows that this applies to win32, that's it. It then traverses the entire
   path from the root, stat()ing each path component - but the initial part,
   \\hostname, is not stat()able, it's not a path; \\hostname\foo is the
   first real component.

   Attached patch fixes this to the best of my understanding of how
   canonicalize_filename_mode() works: it increases `prefix_len` (which
   is bound to be 0 for \\paths) to cover the hostname component, and copies
   the hostname part to `dest` as well - causing canonicalization to start
   at the first real path component and keep the leading \\hostname\ bit
   constant. "

I modified Vaclav's patch to include out-of-bounds handling, and to make
prefix_len point to the slash/backslash after the server name (rather than
past this slash/backslash). Tested with file names of the form
  \\localhost\foo     ->  //localhost\foo
  \\localhost\.\foo   ->  //localhost\foo
  \\localhost\..\foo  ->  //localhost\foo
  \\localhost         ->  //localhost


2020-09-20  Bruno Haible  <bruno@clisp.org>

        canonicalize: Add support for UNC file names on native Windows.
        Reported and initial patch by Vaclav Slavik <vaclav@slavik.io> in
        <https://savannah.gnu.org/bugs/?59079>.
        * lib/canonicalize.c (canonicalize_filename_mode): For UNC file names,
        extend the prefix to include the server.

diff --git a/lib/canonicalize.c b/lib/canonicalize.c
index aa0c3bd..dfdb912 100644
--- a/lib/canonicalize.c
+++ b/lib/canonicalize.c
@@ -163,8 +163,34 @@ canonicalize_filename_mode (const char *name, 
canonicalize_mode_t can_mode)
       *dest++ = '/';
       if (DOUBLE_SLASH_IS_DISTINCT_ROOT)
         {
-          if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len)
-            *dest++ = '/';
+          if (prefix_len == 0 /* implies ISSLASH (name[0]) */
+              && ISSLASH (name[1]) && !ISSLASH (name[2]))
+            {
+              *dest++ = '/';
+#if defined _WIN32 && !defined __CYGWIN__
+              /* For UNC file names '\\server\path\to\file', extend the prefix
+                 to include the server: '\\server\'.  */
+              {
+                size_t i;
+                for (i = 2; name[i] != '\0' && !ISSLASH (name[i]); )
+                  i++;
+                if (name[i] != '\0' /* implies ISSLASH (name[i]) */
+                    && i + 1 < rname_limit - rname)
+                  {
+                    prefix_len = i;
+                    memcpy (dest, name + 2, i - 2 + 1);
+                    dest += i - 2 + 1;
+                  }
+                else
+                  {
+                    /* Either name = '\\server'; this is an invalid file name.
+                       Or name = '\\server\...' and server is more than
+                       PATH_MAX - 4 bytes long.  In either case, stop the UNC
+                       processing.  */
+                  }
+              }
+#endif
+            }
           *dest = '\0';
         }
       start = name + prefix_len;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]