Skip to content

Commit 8ab11dd

Browse files
committed
Fix issue with path canonicalization for Win32 paths
1 parent 1621a37 commit 8ab11dd

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/win32/w32_util.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ size_t git_win32__canonicalize_path(wchar_t *str, size_t len)
132132
static const wchar_t dosdevices_prefix[] = L"\\\?\?\\";
133133
static const wchar_t nt_prefix[] = L"\\\\?\\";
134134
static const wchar_t unc_prefix[] = L"UNC\\";
135+
static const wchar_t unc_canonicalized_prefix[] = L"\\\\";
136+
135137
size_t to_advance = 0;
136138

137139
/* "\??\" -- DOS Devices prefix */
@@ -150,8 +152,18 @@ size_t git_win32__canonicalize_path(wchar_t *str, size_t len)
150152
/* "\??\UNC\", "\\?\UNC\" -- UNC prefix */
151153
if (to_advance && len >= CONST_STRLEN(unc_prefix) &&
152154
!wcsncmp(str + to_advance, unc_prefix, CONST_STRLEN(unc_prefix))) {
153-
to_advance += CONST_STRLEN(unc_prefix);
154-
len -= CONST_STRLEN(unc_prefix);
155+
/**
156+
* The proper Win32 path for a UNC share has "\\" at beginning of it
157+
* and looks like "\\server\share\<folderStructure>".
158+
* So, remove th UNC prefix, but leave room for a "\\"
159+
*/
160+
to_advance += (CONST_STRLEN(unc_prefix) - CONST_STRLEN(unc_canonicalized_prefix));
161+
len -= (CONST_STRLEN(unc_prefix) - CONST_STRLEN(unc_canonicalized_prefix));
162+
163+
/**
164+
* Place a "\\" in the string so the result is "\\server\\share\<folderStructure>"
165+
*/
166+
memmove(str + to_advance, unc_canonicalized_prefix, CONST_STRLEN(unc_canonicalized_prefix) * sizeof(wchar_t));
155167
}
156168

157169
if (to_advance) {

tests/path/win32.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,22 @@ void test_canonicalize(const wchar_t *in, const wchar_t *expected)
145145
#endif
146146
}
147147

148+
void test_path_git_win32__canonicalize_path(const wchar_t *in, const wchar_t *expected)
149+
{
150+
#ifdef GIT_WIN32
151+
git_win32_path canonical;
152+
153+
cl_assert(wcslen(in) < MAX_PATH);
154+
wcscpy(canonical, in);
155+
156+
cl_must_pass(git_win32__canonicalize_path(canonical, wcslen(in)));
157+
cl_assert_equal_wcs(expected, canonical);
158+
#else
159+
GIT_UNUSED(in);
160+
GIT_UNUSED(expected);
161+
#endif
162+
}
163+
148164
void test_path_win32__canonicalize(void)
149165
{
150166
#ifdef GIT_WIN32
@@ -186,6 +202,8 @@ void test_path_win32__canonicalize(void)
186202
test_canonicalize(L"\\\\server\\\\share\\\\foo\\\\bar", L"\\\\server\\share\\foo\\bar");
187203
test_canonicalize(L"\\\\server\\share\\..\\foo", L"\\\\server\\foo");
188204
test_canonicalize(L"\\\\server\\..\\..\\share\\.\\foo", L"\\\\server\\share\\foo");
205+
206+
test_path_git_win32__canonicalize_path(L"\\\\?\\UNC\\server\\C$\\folder", L"\\\\server\\C$\\folder");
189207
#endif
190208
}
191209

0 commit comments

Comments
 (0)