From 3a880bf5e0e4a11719c4ca1e42bd718e712fb0d2 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Sat, 1 Sep 2018 21:01:08 +0200 Subject: [PATCH] Cygwin: fix Win32 path ".." backtracking Commit 35998fc2fa6cbb7d761f6d88346246bd3627552b fixed the buffer underun in win32 path normalization, but introduced a new bug: A wrong assumption led to the inability to backtrack the path outside of the current working directory in case of relative paths. This patch fixes this problem, together with a minor problem if the CWD is on a network share: The result erroneously started with tripple backslash if the src path starts with a single backslash. Signed-off-by: Corinna Vinschen --- winsup/cygwin/path.cc | 21 ++++++++++++++++----- winsup/cygwin/release/2.11.1 | 13 +++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 winsup/cygwin/release/2.11.1 diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 6d8f76db5..3cb46c9c8 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1394,14 +1394,27 @@ normalize_win32_path (const char *src, char *dst, char *&tail) } else if (*src != '/') { + /* Make sure dst points to the rightmost backslash which must not + be backtracked over during ".." evaluation. This is either + the backslash after the network path prefix (i.e. "\\") or + the backslash after a drive letter (i.e. C:\"). */ if (beg_src_slash) - dst = (tail += cygheap->cwd.get_drive (dst)); + { + tail += cygheap->cwd.get_drive (dst); + /* network path, drive == '\\\\'? Decrement tail to avoid + triple backslash in output. */ + if (dst[0] == '\\') + --tail; + dst = tail; + } else if (cygheap->cwd.get (dst, 0)) { tail = strchr (tail, '\0'); if (tail[-1] != '\\') *tail++ = '\\'; - dst = tail - 1; + ++dst; + if (dst[1] == '\\') + ++dst; } else return get_errno (); @@ -1428,9 +1441,7 @@ normalize_win32_path (const char *src, char *dst, char *&tail) } /* Backup if "..". */ - else if (src[0] == '.' && src[1] == '.' - /* dst must be greater than dst_start */ - && tail[-1] == '\\') + else if (src[0] == '.' && src[1] == '.' && tail[-1] == '\\') { if (!isdirsep (src[2]) && src[2] != '\0') *tail++ = *src++; diff --git a/winsup/cygwin/release/2.11.1 b/winsup/cygwin/release/2.11.1 new file mode 100644 index 000000000..c7dfb14c4 --- /dev/null +++ b/winsup/cygwin/release/2.11.1 @@ -0,0 +1,13 @@ +What's new: +----------- + + +What changed: +------------- + + +Bug Fixes +--------- + +- Fix ".." handling in Win32 path normalization, introduced in 2.11.0. + Addresses: https://cygwin.com/ml/cygwin/2018-09/msg00000.html