emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] /srv/bzr/emacs/emacs-24 r111077: Fix bug #13262 with crash


From: Eli Zaretskii
Subject: [Emacs-diffs] /srv/bzr/emacs/emacs-24 r111077: Fix bug #13262 with crashes in completion on MS-Windows with non-ASCII filenames.
Date: Mon, 24 Dec 2012 18:15:13 +0200
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 111077
fixes bug: http://debbugs.gnu.org/13262
committer: Eli Zaretskii <address@hidden>
branch nick: emacs-24
timestamp: Mon 2012-12-24 18:15:13 +0200
message:
  Fix bug #13262 with crashes in completion on MS-Windows with non-ASCII 
filenames.
  
   src/fileio.c (file_name_as_directory, directory_file_name): Accept
   an additional argument MULTIBYTE to indicate whether the input C
   came from a multibyte or a unibyte Lisp string; all callers
   adjusted.  Don't assume the input string is always multibyte.
   (Ffile_name_directory) [DOS_NT]: Handle unibyte strings correctly:
   don't ENCODE_FILE them, and return a unibyte string if the input
   was unibyte.
   (Fexpand_file_name): Don't mix unibyte with multibyte strings, and
   don't assume the input strings will always be multibyte.  If the
   input strings are multibyte, decode strings obtained from C
   library functions.
modified:
  src/ChangeLog
  src/fileio.c
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-12-22 10:12:52 +0000
+++ b/src/ChangeLog     2012-12-24 16:15:13 +0000
@@ -1,3 +1,18 @@
+2012-12-24  Eli Zaretskii  <address@hidden>
+
+       * fileio.c (file_name_as_directory, directory_file_name): Accept
+       an additional argument MULTIBYTE to indicate whether the input C
+       came from a multibyte or a unibyte Lisp string; all callers
+       adjusted.  Don't assume the input string is always multibyte.
+       (Bug#13262)
+       (Ffile_name_directory) [DOS_NT]: Handle unibyte strings correctly:
+       don't ENCODE_FILE them, and return a unibyte string if the input
+       was unibyte.
+       (Fexpand_file_name): Don't mix unibyte with multibyte strings, and
+       don't assume the input strings will always be multibyte.  If the
+       input strings are multibyte, decode strings obtained from C
+       library functions.
+
 2012-12-22  Martin Rudalics  <address@hidden>
 
        * window.c (Fselect_window): Reword doc-string (Bug#13248).

=== modified file 'src/fileio.c'
--- a/src/fileio.c      2012-12-21 11:52:18 +0000
+++ b/src/fileio.c      2012-12-24 16:15:13 +0000
@@ -373,12 +373,26 @@
            strcat (res, "/");
          beg = res;
          p = beg + strlen (beg);
+         dostounix_filename (beg);
+         tem_fn = make_specified_string (beg, -1, p - beg,
+                                         STRING_MULTIBYTE (filename));
        }
-    }
-  tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg,
-                                              STRING_MULTIBYTE (filename)));
-  dostounix_filename (SSDATA (tem_fn));
-  return DECODE_FILE (tem_fn);
+      else
+       tem_fn = make_specified_string (beg - 2, -1, p - beg + 2,
+                                       STRING_MULTIBYTE (filename));
+    }
+  else if (STRING_MULTIBYTE (filename))
+    {
+      tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1));
+      dostounix_filename (SSDATA (tem_fn));
+      tem_fn = DECODE_FILE (tem_fn);
+    }
+  else
+    {
+      dostounix_filename (beg);
+      tem_fn = make_specified_string (beg, -1, p - beg, 0);
+    }
+  return tem_fn;
 #else  /* DOS_NT */
   return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename));
 #endif /* DOS_NT */
@@ -453,12 +467,14 @@
   return Ffile_name_directory (filename);
 }
 
-/* Convert from file name SRC of length SRCLEN to directory name
-   in DST.  On UNIX, just make sure there is a terminating /.
-   Return the length of DST in bytes.  */
+/* Convert from file name SRC of length SRCLEN to directory name in
+   DST.  MULTIBYTE non-zero means the file name in SRC is a multibyte
+   string.  On UNIX, just make sure there is a terminating /.  Return
+   the length of DST in bytes.  */
 
 static ptrdiff_t
-file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen)
+file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
+                       bool multibyte)
 {
   if (srclen == 0)
     {
@@ -477,14 +493,17 @@
       srclen++;
     }
 #ifdef DOS_NT
-  {
-    Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
+  if (multibyte)
+    {
+      Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
 
-    tem_fn = ENCODE_FILE (tem_fn);
-    dostounix_filename (SSDATA (tem_fn));
-    tem_fn = DECODE_FILE (tem_fn);
-    memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
-  }
+      tem_fn = ENCODE_FILE (tem_fn);
+      dostounix_filename (SSDATA (tem_fn));
+      tem_fn = DECODE_FILE (tem_fn);
+      memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
+    }
+  else
+    dostounix_filename (dst);
 #endif
   return srclen;
 }
@@ -520,16 +539,18 @@
     }
 
   buf = alloca (SBYTES (file) + 10);
-  length = file_name_as_directory (buf, SSDATA (file), SBYTES (file));
+  length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
+                                  STRING_MULTIBYTE (file));
   return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file));
 }
 
-/* Convert from directory name SRC of length SRCLEN to
-   file name in DST.  On UNIX, just make sure there isn't
-   a terminating /.  Return the length of DST in bytes.  */
+/* Convert from directory name SRC of length SRCLEN to file name in
+   DST.  MULTIBYTE non-zero means the file name in SRC is a multibyte
+   string.  On UNIX, just make sure there isn't a terminating /.
+   Return the length of DST in bytes.  */
 
 static ptrdiff_t
-directory_file_name (char *dst, char *src, ptrdiff_t srclen)
+directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
 {
   /* Process as Unix format: just remove any final slash.
      But leave "/" unchanged; do not change it to "".  */
@@ -545,14 +566,17 @@
       srclen--;
     }
 #ifdef DOS_NT
-  {
-    Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
+  if (multibyte)
+    {
+      Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
 
-    tem_fn = ENCODE_FILE (tem_fn);
-    dostounix_filename (SSDATA (tem_fn));
-    tem_fn = DECODE_FILE (tem_fn);
-    memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
-  }
+      tem_fn = ENCODE_FILE (tem_fn);
+      dostounix_filename (SSDATA (tem_fn));
+      tem_fn = DECODE_FILE (tem_fn);
+      memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
+    }
+  else
+    dostounix_filename (dst);
 #endif
   return srclen;
 }
@@ -588,7 +612,8 @@
     }
 
   buf = alloca (SBYTES (directory) + 20);
-  length = directory_file_name (buf, SSDATA (directory), SBYTES (directory));
+  length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
+                               STRING_MULTIBYTE (directory));
   return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory));
 }
 
@@ -1038,7 +1063,7 @@
          /* `egetenv' may return a unibyte string, which will bite us since
             we expect the directory to be multibyte.  */
          tem = build_string (newdir);
-         if (!STRING_MULTIBYTE (tem))
+         if (multibyte && !STRING_MULTIBYTE (tem))
            {
              hdir = DECODE_FILE (tem);
              newdir = SSDATA (hdir);
@@ -1060,7 +1085,18 @@
          unblock_input ();
          if (pw)
            {
+             Lisp_Object tem;
+
              newdir = pw->pw_dir;
+             /* `getpwnam' may return a unibyte string, which will
+                bite us since we expect the directory to be
+                multibyte.  */
+             tem = build_string (newdir);
+             if (multibyte && !STRING_MULTIBYTE (tem))
+               {
+                 hdir = DECODE_FILE (tem);
+                 newdir = SSDATA (hdir);
+               }
              nm = p;
 #ifdef DOS_NT
              collapse_newdir = 0;
@@ -1084,6 +1120,13 @@
          adir = alloca (MAXPATHLEN + 1);
          if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
            adir = NULL;
+         else if (multibyte)
+           {
+             Lisp_Object tem = build_string (adir);
+
+             tem = DECODE_FILE (tem);
+             memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
+           }
        }
       if (!adir)
        {
@@ -1142,6 +1185,7 @@
             indirectly by prepending newdir to nm if necessary, and using
             cwd (or the wd of newdir's drive) as the new newdir.  */
          char *adir;
+
          if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
            {
              drive = (unsigned char) newdir[0];
@@ -1151,7 +1195,7 @@
            {
              ptrdiff_t newlen = strlen (newdir);
              char *tmp = alloca (newlen + strlen (nm) + 2);
-             file_name_as_directory (tmp, newdir, newlen);
+             file_name_as_directory (tmp, newdir, newlen, multibyte);
              strcat (tmp, nm);
              nm = tmp;
            }
@@ -1159,10 +1203,17 @@
          if (drive)
            {
              if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
-               newdir = "/";
+               strcpy (adir, "/");
            }
          else
            getwd (adir);
+         if (multibyte)
+           {
+             Lisp_Object tem = build_string (adir);
+
+             tem = DECODE_FILE (tem);
+             memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
+           }
          newdir = adir;
        }
 
@@ -1249,7 +1300,7 @@
            strcpy (target, newdir);
        }
       else
-       file_name_as_directory (target, newdir, length);
+       file_name_as_directory (target, newdir, length, multibyte);
     }
 
   strcat (target, nm);
@@ -1335,9 +1386,14 @@
        target[1] = ':';
       }
     result = make_specified_string (target, -1, o - target, multibyte);
-    result = ENCODE_FILE (result);
-    dostounix_filename (SSDATA (result));
-    result = DECODE_FILE (result);
+    if (multibyte)
+      {
+       result = ENCODE_FILE (result);
+       dostounix_filename (SSDATA (result));
+       result = DECODE_FILE (result);
+      }
+    else
+      dostounix_filename (SSDATA (result));
 #else  /* !DOS_NT */
     result = make_specified_string (target, -1, o - target, multibyte);
 #endif /* !DOS_NT */
@@ -1619,18 +1675,24 @@
   memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
 
 #ifdef DOS_NT
-  {
-    Lisp_Object encoded_filename = ENCODE_FILE (filename);
-    Lisp_Object tem_fn;
+  if (multibyte)
+    {
+      Lisp_Object encoded_filename = ENCODE_FILE (filename);
+      Lisp_Object tem_fn;
 
-    dostounix_filename (SDATA (encoded_filename));
-    tem_fn = DECODE_FILE (encoded_filename);
-    nm = alloca (SBYTES (tem_fn) + 1);
-    memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1);
-    substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
-    if (substituted)
-      filename = tem_fn;
-  }
+      dostounix_filename (SDATA (encoded_filename));
+      tem_fn = DECODE_FILE (encoded_filename);
+      nm = alloca (SBYTES (tem_fn) + 1);
+      memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1);
+      substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
+      if (substituted)
+       filename = tem_fn;
+    }
+  else
+    {
+      dostounix_filename (nm);
+      substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
+    }
 #endif
   endp = nm + SBYTES (filename);
 


reply via email to

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