Skip to content

Commit

Permalink
Merge branch 'wcstombs'
Browse files Browse the repository at this point in the history
This topic branch fixes the problem where a UTF-16 command-line was
converted to UTF-8 in an incorrect way (because Cygwin treated it as if
it was a file name and applied some magic that is intended to allow for
otherwise invalid file names on Windows).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information
dscho committed Jan 5, 2016
2 parents 1edd9a2 + 60a3e9d commit 4c36272
Show file tree
Hide file tree
Showing 14 changed files with 94 additions and 61 deletions.
7 changes: 7 additions & 0 deletions winsup/cygwin/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2015-12-18 Corinna Vinschen <corinna@vinschen.de>

* strfuncs.cc (sys_cp_wcstombs): Delete and move functionality into
sys_wcstombs.
* wchar.h (sys_cp_wcstombs): Drop declaration.
* fhandler_console.cc (dev_console::con_to_str): Call sys_wcstombs.

2015-11-21 Corinna Vinschen <corinna@vinschen.de>

* nlsfuncs.cc (setlocaleinfo): New macro calling __setlocaleinfo.
Expand Down
2 changes: 1 addition & 1 deletion winsup/cygwin/dtable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ handle_to_fn (HANDLE h, char *posix_fn)
if (wcsncasecmp (w32, DEVICE_PREFIX, DEVICE_PREFIX_LEN) != 0
|| !QueryDosDeviceW (NULL, fnbuf, sizeof (fnbuf) / sizeof (WCHAR)))
{
sys_wcstombs (posix_fn, NT_MAX_PATH, w32, w32len);
sys_wcstombs_path (posix_fn, NT_MAX_PATH, w32, w32len);
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion winsup/cygwin/external.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ fillout_pinfo (pid_t pid, int winpid)
ep.rusage_self = p->rusage_self;
ep.rusage_children = p->rusage_children;
ep.progname[0] = '\0';
sys_wcstombs(ep.progname, MAX_PATH, p->progname);
sys_wcstombs_path (ep.progname, MAX_PATH, p->progname);
ep.strace_mask = 0;
ep.version = EXTERNAL_PINFO_VERSION;

Expand Down
3 changes: 1 addition & 2 deletions winsup/cygwin/fhandler_console.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ tty_list::get_cttyp ()
inline DWORD
dev_console::con_to_str (char *d, int dlen, WCHAR w)
{
return sys_cp_wcstombs (cygheap->locale.wctomb, cygheap->locale.charset,
d, dlen, &w, 1);
return sys_wcstombs (d, dlen, &w, 1);
}

inline UINT
Expand Down
6 changes: 3 additions & 3 deletions winsup/cygwin/fhandler_disk_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class __DIR_mounts
char *c = stpcpy (fname, parent_dir);
if (c[- 1] != '/')
*c++ = '/';
sys_wcstombs (c, mounts[idx].Length + 1,
sys_wcstombs_path (c, mounts[idx].Length + 1,
mounts[idx].Buffer, mounts[idx].Length / sizeof (WCHAR));
path_conv pc (fname, PC_SYM_NOFOLLOW | PC_POSIX | PC_KEEP_HANDLE);
if (!stat_worker (pc, &st))
Expand Down Expand Up @@ -2190,7 +2190,7 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
char *p = stpcpy (file, pc.get_posix ());
if (p[-1] != '/')
*p++ = '/';
sys_wcstombs (p, NT_MAX_PATH - (p - file),
sys_wcstombs_path (p, NT_MAX_PATH - (p - file),
fname->Buffer, fname->Length / sizeof (WCHAR));
path_conv fpath (file, PC_SYM_NOFOLLOW);
if (fpath.issymlink ())
Expand All @@ -2211,7 +2211,7 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent *de, DWORD w32_err,
}
}

sys_wcstombs (de->d_name, NAME_MAX + 1, fname->Buffer,
sys_wcstombs_path (de->d_name, NAME_MAX + 1, fname->Buffer,
fname->Length / sizeof (WCHAR));

/* Don't try to optimize relative to dir->__d_position. On several
Expand Down
6 changes: 3 additions & 3 deletions winsup/cygwin/fhandler_netdrive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -255,15 +255,15 @@ fhandler_netdrive::readdir (DIR *dir, dirent *de)
tp.u_get (&ds);
RtlInitUnicodeString (&ss, bs);
RtlDowncaseUnicodeString (&ds, &ss, FALSE);
sys_wcstombs (de->d_name, sizeof de->d_name,
sys_wcstombs_path (de->d_name, sizeof de->d_name,
ds.Buffer, ds.Length / sizeof (WCHAR));
de->d_ino = hash_path_name (get_ino (), de->d_name);
}
else
{
sys_wcstombs (de->d_name, sizeof de->d_name, bs);
sys_wcstombs_path (de->d_name, sizeof de->d_name, bs);
char *rpath = tp.c_get ();
sys_wcstombs (rpath, NT_MAX_PATH, nro->lpRemoteName);
sys_wcstombs_path (rpath, NT_MAX_PATH, nro->lpRemoteName);
de->d_ino = readdir_get_ino (rpath, false);
/* We can't trust remote inode numbers of only 32 bit. That means,
remote NT4 NTFS, as well as shares of Samba version < 3.0. */
Expand Down
11 changes: 6 additions & 5 deletions winsup/cygwin/fhandler_process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -566,10 +566,10 @@ static off_t
format_process_winexename (void *data, char *&destbuf)
{
_pinfo *p = (_pinfo *) data;
size_t len = sys_wcstombs (NULL, 0, p->progname);
size_t len = sys_wcstombs_path (NULL, 0, p->progname);
destbuf = (char *) crealloc_abort (destbuf, len + 1);
/* With trailing \0 for backward compat reasons. */
sys_wcstombs (destbuf, len + 1, p->progname);
sys_wcstombs_path (destbuf, len + 1, p->progname);
return len;
}

Expand Down Expand Up @@ -939,7 +939,7 @@ format_process_maps (void *data, char *&destbuf)
drive_maps.fixup_if_match (msi->SectionFileName.Buffer);
if (mount_table->conv_to_posix_path (dosname,
posix_modname, 0))
sys_wcstombs (posix_modname, NT_MAX_PATH, dosname);
sys_wcstombs_path (posix_modname, NT_MAX_PATH, dosname);
stat64 (posix_modname, &st);
}
else if (!threads.fill_if_match (cur.abase, mb.Type,
Expand Down Expand Up @@ -985,7 +985,7 @@ format_process_stat (void *data, char *&destbuf)
else
{
PWCHAR last_slash = wcsrchr (p->progname, L'\\');
sys_wcstombs (cmd, NAME_MAX + 1,
sys_wcstombs_path (cmd, NAME_MAX + 1,
last_slash ? last_slash + 1 : p->progname);
int len = strlen (cmd);
if (len > 4)
Expand Down Expand Up @@ -1103,7 +1103,8 @@ format_process_status (void *data, char *&destbuf)
vmtext = 0UL, vmshare = 0UL;

PWCHAR last_slash = wcsrchr (p->progname, L'\\');
sys_wcstombs (cmd, NAME_MAX + 1, last_slash ? last_slash + 1 : p->progname);
sys_wcstombs_path (cmd, NAME_MAX + 1,
last_slash ? last_slash + 1 : p->progname);
int len = strlen (cmd);
if (len > 4)
{
Expand Down
9 changes: 5 additions & 4 deletions winsup/cygwin/fhandler_procsys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -243,10 +243,11 @@ fhandler_procsys::fill_filebuf ()
NtClose (h);
if (!NT_SUCCESS (status))
goto unreadable;
len = sys_wcstombs (NULL, 0, target.Buffer, target.Length / sizeof (WCHAR));
len = sys_wcstombs_path (NULL, 0,
target.Buffer, target.Length / sizeof (WCHAR));
filebuf = (char *) crealloc_abort (filebuf, procsys_len + len + 1);
sys_wcstombs (fnamep = stpcpy (filebuf, procsys), len + 1, target.Buffer,
target.Length / sizeof (WCHAR));
sys_wcstombs_path (fnamep = stpcpy (filebuf, procsys), len + 1,
target.Buffer, target.Length / sizeof (WCHAR));
while ((fnamep = strchr (fnamep, '\\')))
*fnamep = '/';
return true;
Expand Down Expand Up @@ -355,7 +356,7 @@ fhandler_procsys::readdir (DIR *dir, dirent *de)
res = ENMFILE;
else
{
sys_wcstombs (de->d_name, NAME_MAX + 1, f.dbi.ObjectName.Buffer,
sys_wcstombs_path (de->d_name, NAME_MAX + 1, f.dbi.ObjectName.Buffer,
f.dbi.ObjectName.Length / sizeof (WCHAR));
de->d_ino = hash_path_name (get_ino (), de->d_name);
if (RtlEqualUnicodeString (&f.dbi.ObjectTypeName, &ro_u_natdir,
Expand Down
8 changes: 4 additions & 4 deletions winsup/cygwin/mount.cc
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
{
/* The filesystem name is only used in fillout_mntent and only if
the filesystem isn't one of the well-known filesystems anyway. */
sys_wcstombs (fsn, sizeof fsn, ffai_buf.ffai.FileSystemName,
sys_wcstombs_path (fsn, sizeof fsn, ffai_buf.ffai.FileSystemName,
ffai_buf.ffai.FileSystemNameLength / sizeof (WCHAR));
strlwr (fsn);
}
Expand Down Expand Up @@ -482,7 +482,7 @@ mount_info::create_root_entry (const PWCHAR root)
/* Create a default root dir derived from the location of the Cygwin DLL.
The entry is immutable, unless the "override" option is given in /etc/fstab. */
char native_root[PATH_MAX];
sys_wcstombs (native_root, PATH_MAX, root);
sys_wcstombs_path (native_root, PATH_MAX, root);
assert (*native_root != '\0');
if (add_item (native_root, "/",
MOUNT_SYSTEM | MOUNT_BINARY | MOUNT_IMMUTABLE | MOUNT_AUTOMATIC | MOUNT_NOACL)
Expand Down Expand Up @@ -868,7 +868,7 @@ mount_info::conv_to_posix_path (PWCHAR src_path, char *posix_path,
}
tmp_pathbuf tp;
char *buf = tp.c_get ();
sys_wcstombs (buf, NT_MAX_PATH, src_path);
sys_wcstombs_path (buf, NT_MAX_PATH, src_path);
int ret = conv_to_posix_path (buf, posix_path, keep_rel_p);
if (changed)
src_path[0] = L'C';
Expand Down Expand Up @@ -1215,7 +1215,7 @@ mount_info::from_fstab_line (char *line, bool user)
{
tmp_pathbuf tp;
char *mb_tmp = tp.c_get ();
sys_wcstombs (mb_tmp, PATH_MAX, tmp);
sys_wcstombs_path (mb_tmp, PATH_MAX, tmp);

mount_flags |= MOUNT_USER_TEMP;
int res = mount_table->add_item (mb_tmp, posix_path, mount_flags);
Expand Down
2 changes: 1 addition & 1 deletion winsup/cygwin/nlsfuncs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@ internal_setlocale ()
if (w_path)
{
char *c_path = tp.c_get ();
sys_wcstombs (c_path, 32768, w_path);
sys_wcstombs_path (c_path, 32768, w_path);
setenv ("PATH", c_path, 1);
}
}
Expand Down
27 changes: 14 additions & 13 deletions winsup/cygwin/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,8 @@ path_conv::check (const UNICODE_STRING *src, unsigned opt,
char *path = tp.c_get ();

user_shared->warned_msdos = true;
sys_wcstombs (path, NT_MAX_PATH, src->Buffer, src->Length / sizeof (WCHAR));
sys_wcstombs_path (path, NT_MAX_PATH,
src->Buffer, src->Length / sizeof (WCHAR));
path_conv::check (path, opt, suffixes);
}

Expand Down Expand Up @@ -2349,7 +2350,7 @@ symlink_info::check_shortcut (HANDLE h)
if (*(PWCHAR) cp == 0xfeff) /* BOM */
{
char *tmpbuf = tp.c_get ();
if (sys_wcstombs (tmpbuf, NT_MAX_PATH, (PWCHAR) (cp + 2))
if (sys_wcstombs_path (tmpbuf, NT_MAX_PATH, (PWCHAR) (cp + 2))
> SYMLINK_MAX)
return 0;
res = posixify (tmpbuf);
Expand Down Expand Up @@ -2430,7 +2431,7 @@ symlink_info::check_sysfile (HANDLE h)
else
srcbuf += 2;
char *tmpbuf = tp.c_get ();
if (sys_wcstombs (tmpbuf, NT_MAX_PATH, (PWCHAR) srcbuf)
if (sys_wcstombs_path (tmpbuf, NT_MAX_PATH, (PWCHAR) srcbuf)
> SYMLINK_MAX)
debug_printf ("symlink string too long");
else
Expand Down Expand Up @@ -2517,7 +2518,7 @@ symlink_info::check_reparse_point (HANDLE h, bool remote)
fileattr &= ~FILE_ATTRIBUTE_REPARSE_POINT;
return 0;
}
sys_wcstombs (srcbuf, SYMLINK_MAX + 7, subst.Buffer,
sys_wcstombs_path (srcbuf, SYMLINK_MAX + 7, subst.Buffer,
subst.Length / sizeof (WCHAR));
pflags |= PATH_SYMLINK | PATH_REP;
/* A symlink is never a directory. */
Expand Down Expand Up @@ -2550,7 +2551,7 @@ symlink_info::check_nfs_symlink (HANDLE h)
{
PWCHAR spath = (PWCHAR)
(pffei->EaName + pffei->EaNameLength + 1);
res = sys_wcstombs (contents, SYMLINK_MAX + 1,
res = sys_wcstombs_path (contents, SYMLINK_MAX + 1,
spath, pffei->EaValueLength);
pflags |= PATH_SYMLINK;
}
Expand Down Expand Up @@ -3614,7 +3615,7 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
}
PUNICODE_STRING up = p.get_nt_native_path ();
buf = tp.c_get ();
sys_wcstombs (buf, NT_MAX_PATH,
sys_wcstombs_path (buf, NT_MAX_PATH,
up->Buffer, up->Length / sizeof (WCHAR));
/* Convert native path to standard DOS path. */
if (!strncmp (buf, "\\??\\", 4))
Expand All @@ -3627,11 +3628,11 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to,
{
/* Device name points to somewhere else in the NT namespace.
Use GLOBALROOT prefix to convert to Win32 path. */
char *p = buf + sys_wcstombs (buf, NT_MAX_PATH,
char *p = buf + sys_wcstombs_path (buf, NT_MAX_PATH,
ro_u_globalroot.Buffer,
ro_u_globalroot.Length
/ sizeof (WCHAR));
sys_wcstombs (p, NT_MAX_PATH - (p - buf),
sys_wcstombs_path (p, NT_MAX_PATH - (p - buf),
up->Buffer, up->Length / sizeof (WCHAR));
}
lsiz = strlen (buf) + 1;
Expand Down Expand Up @@ -4002,8 +4003,8 @@ cygwin_conv_path_list (cygwin_conv_path_t what, const void *from, void *to,
switch (what & CCP_CONVTYPE_MASK)
{
case CCP_WIN_W_TO_POSIX:
if (!sys_wcstombs_alloc (&winp, HEAP_NOTHEAP, (const wchar_t *) from,
(size_t) -1))
if (!sys_wcstombs_alloc_path (&winp, HEAP_NOTHEAP,
(const wchar_t *) from, (size_t) -1))
return -1;
what = (what & ~CCP_CONVTYPE_MASK) | CCP_WIN_A_TO_POSIX;
from = (const void *) winp;
Expand Down Expand Up @@ -4946,9 +4947,9 @@ cwdstuff::get_error_desc () const
void
cwdstuff::reset_posix (wchar_t *w_cwd)
{
size_t len = sys_wcstombs (NULL, (size_t) -1, w_cwd);
size_t len = sys_wcstombs_path (NULL, (size_t) -1, w_cwd);
posix = (char *) crealloc_abort (posix, len + 1);
sys_wcstombs (posix, len + 1, w_cwd);
sys_wcstombs_path (posix, len + 1, w_cwd);
}

char *
Expand All @@ -4973,7 +4974,7 @@ cwdstuff::get (char *buf, int need_posix, int with_chroot, unsigned ulen)
if (!need_posix)
{
tocopy = tp.c_get ();
sys_wcstombs (tocopy, NT_MAX_PATH, win32.Buffer,
sys_wcstombs_path (tocopy, NT_MAX_PATH, win32.Buffer,
win32.Length / sizeof (WCHAR));
}
else
Expand Down
43 changes: 32 additions & 11 deletions winsup/cygwin/strfuncs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static const WCHAR tfx_chars[] = {
0xf000 | '|', '}', '~', 127
};

/* This is the table for the reverse functionality in sys_cp_wcstombs.
/* This is the table for the reverse functionality in sys_wcstombs.
It differs deliberately in two code places (space and dot) to allow
converting back space and dot on filesystems only supporting DOS
filenames. */
Expand Down Expand Up @@ -409,16 +409,18 @@ __big5_mbtowc (struct _reent *r, wchar_t *pwc, const char *s, size_t n,
to buffer size, it's a bug in Cygwin and the buffer in the calling
function should be raised.
*/
size_t __reg3
sys_cp_wcstombs (wctomb_p f_wctomb, const char *charset, char *dst, size_t len,
const wchar_t *src, size_t nwc)
static size_t __reg3
sys_wcstombs (char *dst, size_t len, const wchar_t *src, size_t nwc,
bool is_path)
{
char buf[10];
char *ptr = dst;
wchar_t *pwcs = (wchar_t *) src;
size_t n = 0;
mbstate_t ps;
save_errno save;
wctomb_p f_wctomb = cygheap->locale.wctomb;
const char *charset = cygheap->locale.charset;

memset (&ps, 0, sizeof ps);
if (dst == NULL)
Expand All @@ -433,7 +435,7 @@ sys_cp_wcstombs (wctomb_p f_wctomb, const char *charset, char *dst, size_t len,
ASCII area <= 0x7f (only for path names) is transform_chars above.
Reverse functionality for invalid bytes in a multibyte sequence is
in sys_cp_mbstowcs below. */
if ((pw & 0xff00) == 0xf000
if (is_path && (pw & 0xff00) == 0xf000
&& (((cwc = (pw & 0xff)) <= 0x7f && tfx_rev_chars[cwc] >= 0xf000)
|| (cwc >= 0x80 && MB_CUR_MAX > 1)))
{
Expand Down Expand Up @@ -495,11 +497,16 @@ sys_cp_wcstombs (wctomb_p f_wctomb, const char *charset, char *dst, size_t len,
return n;
}

size_t __reg3
sys_wcstombs_path (char *dst, size_t len, const wchar_t * src, size_t nwc)
{
return sys_wcstombs (dst, len, src, nwc, true);
}

size_t __reg3
sys_wcstombs (char *dst, size_t len, const wchar_t * src, size_t nwc)
{
return sys_cp_wcstombs (cygheap->locale.wctomb, cygheap->locale.charset,
dst, len, src, nwc);
return sys_wcstombs (dst, len, src, nwc, false);
}

/* Allocate a buffer big enough for the string, always including the
Expand All @@ -512,12 +519,13 @@ sys_wcstombs (char *dst, size_t len, const wchar_t * src, size_t nwc)
Note that this code is shared by cygserver (which requires it via
__small_vsprintf) and so when built there plain calloc is the
only choice. */
size_t __reg3
sys_wcstombs_alloc (char **dst_p, int type, const wchar_t *src, size_t nwc)
static size_t __reg3
sys_wcstombs_alloc (char **dst_p, int type, const wchar_t *src, size_t nwc,
bool is_path)
{
size_t ret;

ret = sys_wcstombs (NULL, (size_t) -1, src, nwc);
ret = sys_wcstombs (NULL, (size_t) -1, src, nwc, is_path);
if (ret > 0)
{
size_t dlen = ret + 1;
Expand All @@ -528,11 +536,24 @@ sys_wcstombs_alloc (char **dst_p, int type, const wchar_t *src, size_t nwc)
*dst_p = (char *) ccalloc ((cygheap_types) type, dlen, sizeof (char));
if (!*dst_p)
return 0;
ret = sys_wcstombs (*dst_p, dlen, src, nwc);
ret = sys_wcstombs (*dst_p, dlen, src, nwc, is_path);
}
return ret;
}

size_t __reg3
sys_wcstombs_alloc_path (char **dst_p, int type, const wchar_t *src, size_t nwc)
{
return sys_wcstombs_alloc (dst_p, type, src, nwc, true);
}

size_t __reg3
sys_wcstombs_alloc (char **dst_p, int type, const wchar_t *src,
size_t nwc)
{
return sys_wcstombs_alloc (dst_p, type, src, nwc, false);
}

/* sys_cp_mbstowcs is actually most of the time called as sys_mbstowcs with
a 0 codepage. If cp is not 0, the codepage is evaluated and used for the
conversion. This is so that fhandler_console can switch to an alternate
Expand Down
Loading

0 comments on commit 4c36272

Please sign in to comment.