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 Sep 6, 2023
2 parents d88a70f + 9ad0bae commit 35615be
Show file tree
Hide file tree
Showing 14 changed files with 68 additions and 60 deletions.
5 changes: 5 additions & 0 deletions newlib/libc/locale/lctype.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@

#define LCCTYPE_SIZE (sizeof(struct lc_ctype_T) / sizeof(char *))

#ifdef __CYGWIN__
/* Cygwin uses __utf8_mbtowc() by default, therefore mb_cur_max := 6 */
static char numone[] = { '\x06', '\0'};
#else
static char numone[] = { '\1', '\0'};
#endif

const struct lc_ctype_T _C_ctype_locale = {
"ASCII", /* codeset */
Expand Down
4 changes: 2 additions & 2 deletions winsup/cygwin/dcrt0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -908,9 +908,9 @@ dll_crt0_1 (void *)
if (!__argc)
{
PWCHAR wline = GetCommandLineW ();
size_t size = sys_wcstombs_no_path (NULL, 0, wline) + 1;
size_t size = sys_wcstombs (NULL, 0, wline) + 1;
char *line = (char *) alloca (size);
sys_wcstombs_no_path (line, size, wline);
sys_wcstombs (line, size, wline);

/* Scan the command line and build argv. Expand wildcards if not
called from another cygwin process. */
Expand Down
2 changes: 1 addition & 1 deletion winsup/cygwin/dtable.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1022,7 +1022,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
8 changes: 4 additions & 4 deletions winsup/cygwin/environ.cc
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ win32env_to_cygenv (PWCHAR rawenv, bool posify)
eventually want to use them). */
for (i = 0, w = rawenv; *w != L'\0'; w = wcschr (w, L'\0') + 1, i++)
{
sys_wcstombs_alloc_no_path (&newp, HEAP_NOTHEAP, w);
sys_wcstombs_alloc (&newp, HEAP_NOTHEAP, w);
if (i >= envc)
envp = (char **) realloc (envp, (4 + (envc += 100)) * sizeof (char *));
envp[i] = newp;
Expand Down Expand Up @@ -977,15 +977,15 @@ getwinenveq (const char *name, size_t namelen, int x)
int totlen = GetEnvironmentVariableW (name0, valbuf, 32768);
if (totlen > 0)
{
totlen = sys_wcstombs_no_path (NULL, 0, valbuf) + 1;
totlen = sys_wcstombs (NULL, 0, valbuf) + 1;
if (x == HEAP_1_STR)
totlen += namelen;
else
namelen = 0;
char *p = (char *) cmalloc_abort ((cygheap_types) x, totlen);
if (namelen)
strcpy (p, name);
sys_wcstombs_no_path (p + namelen, totlen, valbuf);
sys_wcstombs (p + namelen, totlen, valbuf);
debug_printf ("using value from GetEnvironmentVariable for '%W'", name0);
return p;
}
Expand Down Expand Up @@ -1143,7 +1143,7 @@ build_env (const char * const *envp, PWCHAR &envblock, int &envc,
for (winnum = 0, var = cwinenv;
*var;
++winnum, var = wcschr (var, L'\0') + 1)
sys_wcstombs_alloc_no_path (&winenv[winnum], HEAP_NOTHEAP, var);
sys_wcstombs_alloc (&winenv[winnum], HEAP_NOTHEAP, var);
}
DestroyEnvironmentBlock (cwinenv);
/* Eliminate variables which are already available in envp, as well as
Expand Down
2 changes: 1 addition & 1 deletion winsup/cygwin/external.cc
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,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
4 changes: 2 additions & 2 deletions winsup/cygwin/fhandler/disk_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2134,7 +2134,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 @@ -2155,7 +2155,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 @@ -283,15 +283,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 @@ -574,10 +574,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 @@ -1048,7 +1048,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);
stat (posix_modname, &st);
}
else if (!threads.fill_if_match (cur.abase, mb.Type,
Expand Down Expand Up @@ -1103,7 +1103,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 @@ -1210,7 +1210,8 @@ format_process_status (void *data, char *&destbuf)
bool fetch_siginfo = false;

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
11 changes: 6 additions & 5 deletions winsup/cygwin/fhandler/procsys.cc
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,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 @@ -377,8 +378,8 @@ fhandler_procsys::readdir (DIR *dir, dirent *de)
res = ENMFILE;
else
{
sys_wcstombs (de->d_name, NAME_MAX + 1, dbi->ObjectName.Buffer,
dbi->ObjectName.Length / sizeof (WCHAR));
sys_wcstombs_path (de->d_name, NAME_MAX + 1, dbi->ObjectName.Buffer,
dbi->ObjectName.Length / sizeof (WCHAR));
de->d_ino = hash_path_name (get_ino (), de->d_name);
if (RtlEqualUnicodeString (&dbi->ObjectTypeName, &ro_u_natdir, FALSE))
de->d_type = DT_DIR;
Expand Down
16 changes: 8 additions & 8 deletions winsup/cygwin/local_includes/wchar.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,29 @@ extern size_t _sys_wcstombs_alloc (char **dst_p, int type, const wchar_t *src,
size_t nwc, bool is_path);

static inline size_t
sys_wcstombs (char *dst, size_t len, const wchar_t * src,
size_t nwc = (size_t) -1)
sys_wcstombs_path (char *dst, size_t len, const wchar_t * src,
size_t nwc = (size_t) -1)
{
return _sys_wcstombs (dst, len, src, nwc, true);
}

static inline size_t
sys_wcstombs_no_path (char *dst, size_t len, const wchar_t * src,
size_t nwc = (size_t) -1)
sys_wcstombs (char *dst, size_t len, const wchar_t * src,
size_t nwc = (size_t) -1)
{
return _sys_wcstombs (dst, len, src, nwc, false);
}

static inline size_t
sys_wcstombs_alloc (char **dst_p, int type, const wchar_t *src,
size_t nwc = (size_t) -1)
sys_wcstombs_alloc_path (char **dst_p, int type, const wchar_t *src,
size_t nwc = (size_t) -1)
{
return _sys_wcstombs_alloc (dst_p, type, src, nwc, true);
}

static inline size_t
sys_wcstombs_alloc_no_path (char **dst_p, int type, const wchar_t *src,
size_t nwc = (size_t) -1)
sys_wcstombs_alloc (char **dst_p, int type, const wchar_t *src,
size_t nwc = (size_t) -1)
{
return _sys_wcstombs_alloc (dst_p, type, src, nwc, false);
}
Expand Down
8 changes: 4 additions & 4 deletions winsup/cygwin/mount.cc
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,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 All @@ -490,7 +490,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_IMMUTABLE | MOUNT_AUTOMATIC | MOUNT_NOACL)
Expand Down Expand Up @@ -877,7 +877,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, ccp_flags);
if (changed)
src_path[0] = L'C';
Expand Down Expand Up @@ -1211,7 +1211,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 @@ -1596,7 +1596,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
29 changes: 15 additions & 14 deletions winsup/cygwin/path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,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 @@ -2574,7 +2575,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 @@ -2655,7 +2656,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 @@ -2923,8 +2924,8 @@ symlink_info::check_reparse_point (HANDLE h, bool remote)
path_flags |= ret;
if (ret & PATH_SYMLINK)
{
sys_wcstombs (srcbuf, SYMLINK_MAX + 7, symbuf.Buffer,
symbuf.Length / sizeof (WCHAR));
sys_wcstombs_path (srcbuf, SYMLINK_MAX + 7, symbuf.Buffer,
symbuf.Length / sizeof (WCHAR));
/* A symlink is never a directory. */
fileattr &= ~FILE_ATTRIBUTE_DIRECTORY;
return posixify (srcbuf);
Expand Down Expand Up @@ -2958,7 +2959,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);
path_flags |= PATH_SYMLINK;
}
Expand Down Expand Up @@ -4143,7 +4144,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 @@ -4156,11 +4157,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 @@ -4470,8 +4471,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 @@ -5349,9 +5350,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 @@ -5376,7 +5377,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
Loading

0 comments on commit 35615be

Please sign in to comment.