aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-12-24 18:15:13 +0200
committerEli Zaretskii2012-12-24 18:15:13 +0200
commitf5c81c80c109fcaca04b25e08c34848110e2550b (patch)
treeab61da6d934e63e361fb1a4915a59325ee95ac9c /src
parent216ed9cc435743a596b04917605d29f5ea562e7e (diff)
downloademacs-f5c81c80c109fcaca04b25e08c34848110e2550b.tar.gz
emacs-f5c81c80c109fcaca04b25e08c34848110e2550b.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog15
-rw-r--r--src/fileio.c156
2 files changed, 124 insertions, 47 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index e8d5449a99e..c8cc486a9de 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,18 @@
12012-12-24 Eli Zaretskii <eliz@gnu.org>
2
3 * fileio.c (file_name_as_directory, directory_file_name): Accept
4 an additional argument MULTIBYTE to indicate whether the input C
5 came from a multibyte or a unibyte Lisp string; all callers
6 adjusted. Don't assume the input string is always multibyte.
7 (Bug#13262)
8 (Ffile_name_directory) [DOS_NT]: Handle unibyte strings correctly:
9 don't ENCODE_FILE them, and return a unibyte string if the input
10 was unibyte.
11 (Fexpand_file_name): Don't mix unibyte with multibyte strings, and
12 don't assume the input strings will always be multibyte. If the
13 input strings are multibyte, decode strings obtained from C
14 library functions.
15
12012-12-22 Martin Rudalics <rudalics@gmx.at> 162012-12-22 Martin Rudalics <rudalics@gmx.at>
2 17
3 * window.c (Fselect_window): Reword doc-string (Bug#13248). 18 * window.c (Fselect_window): Reword doc-string (Bug#13248).
diff --git a/src/fileio.c b/src/fileio.c
index b0c319cfa62..2d72583e506 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -373,12 +373,26 @@ Given a Unix syntax file name, returns a string ending in slash. */)
373 strcat (res, "/"); 373 strcat (res, "/");
374 beg = res; 374 beg = res;
375 p = beg + strlen (beg); 375 p = beg + strlen (beg);
376 dostounix_filename (beg);
377 tem_fn = make_specified_string (beg, -1, p - beg,
378 STRING_MULTIBYTE (filename));
376 } 379 }
380 else
381 tem_fn = make_specified_string (beg - 2, -1, p - beg + 2,
382 STRING_MULTIBYTE (filename));
383 }
384 else if (STRING_MULTIBYTE (filename))
385 {
386 tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 1));
387 dostounix_filename (SSDATA (tem_fn));
388 tem_fn = DECODE_FILE (tem_fn);
389 }
390 else
391 {
392 dostounix_filename (beg);
393 tem_fn = make_specified_string (beg, -1, p - beg, 0);
377 } 394 }
378 tem_fn = ENCODE_FILE (make_specified_string (beg, -1, p - beg, 395 return tem_fn;
379 STRING_MULTIBYTE (filename)));
380 dostounix_filename (SSDATA (tem_fn));
381 return DECODE_FILE (tem_fn);
382#else /* DOS_NT */ 396#else /* DOS_NT */
383 return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename)); 397 return make_specified_string (beg, -1, p - beg, STRING_MULTIBYTE (filename));
384#endif /* DOS_NT */ 398#endif /* DOS_NT */
@@ -453,12 +467,14 @@ get a current directory to run processes in. */)
453 return Ffile_name_directory (filename); 467 return Ffile_name_directory (filename);
454} 468}
455 469
456/* Convert from file name SRC of length SRCLEN to directory name 470/* Convert from file name SRC of length SRCLEN to directory name in
457 in DST. On UNIX, just make sure there is a terminating /. 471 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte
458 Return the length of DST in bytes. */ 472 string. On UNIX, just make sure there is a terminating /. Return
473 the length of DST in bytes. */
459 474
460static ptrdiff_t 475static ptrdiff_t
461file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen) 476file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
477 bool multibyte)
462{ 478{
463 if (srclen == 0) 479 if (srclen == 0)
464 { 480 {
@@ -477,14 +493,17 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen)
477 srclen++; 493 srclen++;
478 } 494 }
479#ifdef DOS_NT 495#ifdef DOS_NT
480 { 496 if (multibyte)
481 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); 497 {
498 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
482 499
483 tem_fn = ENCODE_FILE (tem_fn); 500 tem_fn = ENCODE_FILE (tem_fn);
484 dostounix_filename (SSDATA (tem_fn)); 501 dostounix_filename (SSDATA (tem_fn));
485 tem_fn = DECODE_FILE (tem_fn); 502 tem_fn = DECODE_FILE (tem_fn);
486 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); 503 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
487 } 504 }
505 else
506 dostounix_filename (dst);
488#endif 507#endif
489 return srclen; 508 return srclen;
490} 509}
@@ -520,16 +539,18 @@ For a Unix-syntax file name, just appends a slash. */)
520 } 539 }
521 540
522 buf = alloca (SBYTES (file) + 10); 541 buf = alloca (SBYTES (file) + 10);
523 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file)); 542 length = file_name_as_directory (buf, SSDATA (file), SBYTES (file),
543 STRING_MULTIBYTE (file));
524 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file)); 544 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (file));
525} 545}
526 546
527/* Convert from directory name SRC of length SRCLEN to 547/* Convert from directory name SRC of length SRCLEN to file name in
528 file name in DST. On UNIX, just make sure there isn't 548 DST. MULTIBYTE non-zero means the file name in SRC is a multibyte
529 a terminating /. Return the length of DST in bytes. */ 549 string. On UNIX, just make sure there isn't a terminating /.
550 Return the length of DST in bytes. */
530 551
531static ptrdiff_t 552static ptrdiff_t
532directory_file_name (char *dst, char *src, ptrdiff_t srclen) 553directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
533{ 554{
534 /* Process as Unix format: just remove any final slash. 555 /* Process as Unix format: just remove any final slash.
535 But leave "/" unchanged; do not change it to "". */ 556 But leave "/" unchanged; do not change it to "". */
@@ -545,14 +566,17 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen)
545 srclen--; 566 srclen--;
546 } 567 }
547#ifdef DOS_NT 568#ifdef DOS_NT
548 { 569 if (multibyte)
549 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1); 570 {
571 Lisp_Object tem_fn = make_specified_string (dst, -1, srclen, 1);
550 572
551 tem_fn = ENCODE_FILE (tem_fn); 573 tem_fn = ENCODE_FILE (tem_fn);
552 dostounix_filename (SSDATA (tem_fn)); 574 dostounix_filename (SSDATA (tem_fn));
553 tem_fn = DECODE_FILE (tem_fn); 575 tem_fn = DECODE_FILE (tem_fn);
554 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1); 576 memcpy (dst, SSDATA (tem_fn), (srclen = SBYTES (tem_fn)) + 1);
555 } 577 }
578 else
579 dostounix_filename (dst);
556#endif 580#endif
557 return srclen; 581 return srclen;
558} 582}
@@ -588,7 +612,8 @@ In Unix-syntax, this function just removes the final slash. */)
588 } 612 }
589 613
590 buf = alloca (SBYTES (directory) + 20); 614 buf = alloca (SBYTES (directory) + 20);
591 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory)); 615 length = directory_file_name (buf, SSDATA (directory), SBYTES (directory),
616 STRING_MULTIBYTE (directory));
592 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory)); 617 return make_specified_string (buf, -1, length, STRING_MULTIBYTE (directory));
593} 618}
594 619
@@ -1038,7 +1063,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1038 /* `egetenv' may return a unibyte string, which will bite us since 1063 /* `egetenv' may return a unibyte string, which will bite us since
1039 we expect the directory to be multibyte. */ 1064 we expect the directory to be multibyte. */
1040 tem = build_string (newdir); 1065 tem = build_string (newdir);
1041 if (!STRING_MULTIBYTE (tem)) 1066 if (multibyte && !STRING_MULTIBYTE (tem))
1042 { 1067 {
1043 hdir = DECODE_FILE (tem); 1068 hdir = DECODE_FILE (tem);
1044 newdir = SSDATA (hdir); 1069 newdir = SSDATA (hdir);
@@ -1060,7 +1085,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1060 unblock_input (); 1085 unblock_input ();
1061 if (pw) 1086 if (pw)
1062 { 1087 {
1088 Lisp_Object tem;
1089
1063 newdir = pw->pw_dir; 1090 newdir = pw->pw_dir;
1091 /* `getpwnam' may return a unibyte string, which will
1092 bite us since we expect the directory to be
1093 multibyte. */
1094 tem = build_string (newdir);
1095 if (multibyte && !STRING_MULTIBYTE (tem))
1096 {
1097 hdir = DECODE_FILE (tem);
1098 newdir = SSDATA (hdir);
1099 }
1064 nm = p; 1100 nm = p;
1065#ifdef DOS_NT 1101#ifdef DOS_NT
1066 collapse_newdir = 0; 1102 collapse_newdir = 0;
@@ -1084,6 +1120,13 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1084 adir = alloca (MAXPATHLEN + 1); 1120 adir = alloca (MAXPATHLEN + 1);
1085 if (!getdefdir (c_toupper (drive) - 'A' + 1, adir)) 1121 if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
1086 adir = NULL; 1122 adir = NULL;
1123 else if (multibyte)
1124 {
1125 Lisp_Object tem = build_string (adir);
1126
1127 tem = DECODE_FILE (tem);
1128 memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
1129 }
1087 } 1130 }
1088 if (!adir) 1131 if (!adir)
1089 { 1132 {
@@ -1142,6 +1185,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1142 indirectly by prepending newdir to nm if necessary, and using 1185 indirectly by prepending newdir to nm if necessary, and using
1143 cwd (or the wd of newdir's drive) as the new newdir. */ 1186 cwd (or the wd of newdir's drive) as the new newdir. */
1144 char *adir; 1187 char *adir;
1188
1145 if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1])) 1189 if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
1146 { 1190 {
1147 drive = (unsigned char) newdir[0]; 1191 drive = (unsigned char) newdir[0];
@@ -1151,7 +1195,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1151 { 1195 {
1152 ptrdiff_t newlen = strlen (newdir); 1196 ptrdiff_t newlen = strlen (newdir);
1153 char *tmp = alloca (newlen + strlen (nm) + 2); 1197 char *tmp = alloca (newlen + strlen (nm) + 2);
1154 file_name_as_directory (tmp, newdir, newlen); 1198 file_name_as_directory (tmp, newdir, newlen, multibyte);
1155 strcat (tmp, nm); 1199 strcat (tmp, nm);
1156 nm = tmp; 1200 nm = tmp;
1157 } 1201 }
@@ -1159,10 +1203,17 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1159 if (drive) 1203 if (drive)
1160 { 1204 {
1161 if (!getdefdir (c_toupper (drive) - 'A' + 1, adir)) 1205 if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
1162 newdir = "/"; 1206 strcpy (adir, "/");
1163 } 1207 }
1164 else 1208 else
1165 getwd (adir); 1209 getwd (adir);
1210 if (multibyte)
1211 {
1212 Lisp_Object tem = build_string (adir);
1213
1214 tem = DECODE_FILE (tem);
1215 memcpy (adir, SSDATA (tem), SBYTES (tem) + 1);
1216 }
1166 newdir = adir; 1217 newdir = adir;
1167 } 1218 }
1168 1219
@@ -1249,7 +1300,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1249 strcpy (target, newdir); 1300 strcpy (target, newdir);
1250 } 1301 }
1251 else 1302 else
1252 file_name_as_directory (target, newdir, length); 1303 file_name_as_directory (target, newdir, length, multibyte);
1253 } 1304 }
1254 1305
1255 strcat (target, nm); 1306 strcat (target, nm);
@@ -1335,9 +1386,14 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1335 target[1] = ':'; 1386 target[1] = ':';
1336 } 1387 }
1337 result = make_specified_string (target, -1, o - target, multibyte); 1388 result = make_specified_string (target, -1, o - target, multibyte);
1338 result = ENCODE_FILE (result); 1389 if (multibyte)
1339 dostounix_filename (SSDATA (result)); 1390 {
1340 result = DECODE_FILE (result); 1391 result = ENCODE_FILE (result);
1392 dostounix_filename (SSDATA (result));
1393 result = DECODE_FILE (result);
1394 }
1395 else
1396 dostounix_filename (SSDATA (result));
1341#else /* !DOS_NT */ 1397#else /* !DOS_NT */
1342 result = make_specified_string (target, -1, o - target, multibyte); 1398 result = make_specified_string (target, -1, o - target, multibyte);
1343#endif /* !DOS_NT */ 1399#endif /* !DOS_NT */
@@ -1619,18 +1675,24 @@ those `/' is discarded. */)
1619 memcpy (nm, SDATA (filename), SBYTES (filename) + 1); 1675 memcpy (nm, SDATA (filename), SBYTES (filename) + 1);
1620 1676
1621#ifdef DOS_NT 1677#ifdef DOS_NT
1622 { 1678 if (multibyte)
1623 Lisp_Object encoded_filename = ENCODE_FILE (filename); 1679 {
1624 Lisp_Object tem_fn; 1680 Lisp_Object encoded_filename = ENCODE_FILE (filename);
1625 1681 Lisp_Object tem_fn;
1626 dostounix_filename (SDATA (encoded_filename)); 1682
1627 tem_fn = DECODE_FILE (encoded_filename); 1683 dostounix_filename (SDATA (encoded_filename));
1628 nm = alloca (SBYTES (tem_fn) + 1); 1684 tem_fn = DECODE_FILE (encoded_filename);
1629 memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1); 1685 nm = alloca (SBYTES (tem_fn) + 1);
1630 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0); 1686 memcpy (nm, SDATA (tem_fn), SBYTES (tem_fn) + 1);
1631 if (substituted) 1687 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1632 filename = tem_fn; 1688 if (substituted)
1633 } 1689 filename = tem_fn;
1690 }
1691 else
1692 {
1693 dostounix_filename (nm);
1694 substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
1695 }
1634#endif 1696#endif
1635 endp = nm + SBYTES (filename); 1697 endp = nm + SBYTES (filename);
1636 1698