10000 path: use proper size for win32 api calls · libgit2/libgit2@5389ccb · GitHub
[go: up one dir, main page]

Skip to content

Commit 5389ccb

Browse files
committed
path: use proper size for win32 api calls
1 parent 0fdb7ad commit 5389ccb

File tree

4 files changed

+56
-30
lines changed

4 files changed

+56
-30
lines changed

src/path.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <stdio.h>
2222
#include <ctype.h>
2323

24+
extern bool git_win32_longpaths_support;
25+
2426
static int dos_drive_prefix_length(const char *path)
2527
{
2628
int i;
@@ -1244,14 +1246,16 @@ int git_path_diriter_init(
12441246
static int diriter_update_paths(git_path_diriter *diriter)
12451247
{
12461248
size_t filename_len, path_len;
1247-
1249+
size_t max_path_utf16_length = git_win32_longpaths_support
1250+
? GIT_WIN_PATH_UTF16
1251+
: GIT_WIN_SHORT_PATH_UTF16;
12481252
filename_len = wcslen(diriter->current.cFileName);
12491253

12501254
if (GIT_ADD_SIZET_OVERFLOW(&path_len, diriter->parent_len, filename_len) ||
12511255
GIT_ADD_SIZET_OVERFLOW(&path_len, path_len, 2))
12521256
return -1;
12531257

1254-
if (path_len > GIT_WIN_PATH_UTF16) {
1258+
if (path_len > max_path_utf16_length) {
12551259
git_error_set(GIT_ERROR_FILESYSTEM,
12561260
"invalid path '%.*ls\\%ls' (path too long)",
12571261
diriter->parent_len, diriter->path, diriter->current.cFileName);

src/win32/path_w32.c

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ int git_win32_path_canonicalize(git_win32_path path)
8888
{
8989
wchar_t *base, *from, *to, *next;
9090
size_t len;
91-
size_t max_path_length = git_win32_longpaths_support
92-
? GIT_WIN_PATH_UTF16
93-
: GIT_WIN_SHORT_PATH_UTF16;
9491

9592
base = to = path__skip_prefix(path);
9693

< D7AE div class="d-flex flex-row">
@@ -147,22 +144,20 @@ int git_win32_path_canonicalize(git_win32_path path)
147144
while (to > base && to[-1] == L'\\') to--;
148145

149146
*to = L'\0';
150-
len = to - path;
151-
if (len >= 8 && wcsncmp(L"\\\\?\\UNC\\", path, 8) != 0) {
152-
/* Not a UNC path, max length shorter by 2 */
153-
max_path_length -= 2;
154-
}
155-
if (len >= max_path_length) {
147+
if ((to - path) > INT_MAX) {
156148
SetLastError(ERROR_FILENAME_EXCED_RANGE);
157149
return -1;
158150
}
159151

160-
return (int)len;
152+
return (int)(to - path);
161153
}
162154

163155
static int win32_path_cwd(wchar_t *out, size_t len)
164156
{
165157
int cwd_len;
158+
int max_path_length = git_win32_longpaths_support
159+
? WIN_GIT_PATH_MAX
160+
: WIN_GIT_SHORT_PATH_MAX;
166161

167162
if (len > INT_MAX) {
168163
errno = ENAMETOOLONG;
@@ -179,7 +174,7 @@ static int win32_path_cwd(wchar_t *out, size_t len)
179174
* '\'s, but we we add a 'UNC' specifier to the path, plus
180175
* a trailing directory separator, plus a NUL.
181176
*/
182-
if (cwd_len > WIN_GIT_PATH_MAX - 4) {
177+
if (cwd_len > max_path_length - 4) {
183178
errno = ENAMETOOLONG;
184179
return -1;
185180
}
@@ -196,7 +191,7 @@ static int win32_path_cwd(wchar_t *out, size_t len)
196191
* working directory. (One character for the directory separator,
197192
* one for the null.
198193
*/
199-
else if (cwd_len > WIN_GIT_PATH_MAX - 2) {
194+
else if (cwd_len > max_path_length - 2) {
200195
errno = ENAMETOOLONG;
201196
return -1;
202197
}
@@ -207,20 +202,23 @@ static int win32_path_cwd(wchar_t *out, size_t len)
207202
int git_win32_path_from_utf8(git_win32_path out, const char *src)
208203
{
209204
wchar_t *dest = out;
205+
size_t max_path_length = git_win32_longpaths_support
206+
? WIN_GIT_PATH_MAX
207+
: WIN_GIT_SHORT_PATH_MAX;
210208

211209
/* All win32 paths are in NT-prefixed format, beginning with "\\?\". */
212210
memcpy(dest, PATH__NT_NAMESPACE, sizeof(wchar_t) * PATH__NT_NAMESPACE_LEN);
213211
dest += PATH__NT_NAMESPACE_LEN;
214212

215213
/* See if this is an absolute path (beginning with a drive letter) */
216214
if (git_path_is_absolute(src)) {
217-
if (git__utf8_to_16(dest, WIN_GIT_PATH_MAX, src) < 0)
215+
if (git__utf8_to_16(dest, max_path_length, src) < 0)
218216
goto on_error;
219217
}
220218
/* File-prefixed NT-style paths beginning with \\?\ */
221219
else if (path__is_nt_namespace(src)) {
222220
/* Skip the NT prefix, the destination already contains it */
223-
if (git__utf8_to_16(dest, WIN_GIT_PATH_MAX, src + PATH__NT_NAMESPACE_LEN) < 0)
221+
if (git__utf8_to_16(dest, max_path_length, src + PATH__NT_NAMESPACE_LEN) < 0)
224222
goto on_error;
225223
}
226224
/* UNC paths */
@@ -229,12 +227,12 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
229227
dest += 4;
230228

231229
/* Skip the leading "\\" */
232-
if (git__utf8_to_16(dest, WIN_GIT_PATH_MAX - 2, src + 2) < 0)
230+
if (git__utf8_to_16(dest, max_path_length - 2, src + 2) < 0)
233231
goto on_error;
234232
}
235233
/* Absolute paths omitting the drive letter */
236234
else if (path__startswith_slash(src)) {
237-
if (path__cwd(dest, WIN_GIT_MAX_PATH) < 0)
235+
if (path__cwd(dest, (int)max_path_length) < 0)
238236
goto on_error;
239237

240238
if (!git_path_is_absolute(dest)) {
@@ -243,19 +241,19 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
243241
}
244242

245243
/* Skip the drive letter specification ("C:") */
246-
if (git__utf8_to_16(dest + 2, WIN_GIT_PATH_MAX - 2, src) < 0)
244+
if (git__utf8_to_16(dest + 2, max_path_length - 2, src) < 0)
247245
goto on_error;
248246
}
249247
/* Relative paths */
250248
else {
251249
int cwd_len;
252250

253-
if ((cwd_len = win32_path_cwd(dest, WIN_GIT_PATH_MAX)) < 0)
251+
if ((cwd_len = win32_path_cwd(dest, max_path_length)) < 0)
254252
goto on_error;
255253

256254
dest[cwd_len++] = L'\\';
257255

258-
if (git__utf8_to_16(dest + cwd_len, WIN_GIT_PATH_MAX - cwd_len, src) < 0)
256+
if (git__utf8_to_16(dest + cwd_len, max_path_length - cwd_len, src) < 0)
259257
goto on_error;
260258
}
261259

@@ -273,6 +271,9 @@ int git_win32_path_relative_from_utf8(git_win32_path out, const char *src)
273271
{
274272
wchar_t *dest = out, *p;
275273
int len;
274+
size_t max_path_length = git_win32_longpaths_support
275+
? WIN_GIT_PATH_MAX
276+
: WIN_GIT_SHORT_PATH_MAX;
276277

277278
/* Handle absolute paths */
278279
if (git_path_is_absolute(src) ||
@@ -282,7 +283,7 @@ int git_win32_path_relative_from_utf8(git_win32_path out, const char *src)
282283
return git_win32_path_from_utf8(out, src);
283284
}
284285

285-
if ((len = git__utf8_to_16(dest, WIN_GIT_MAX_PATH, src)) < 0)
286+
if ((len = git__utf8_to_16(dest, max_path_length, src)) < 0)
286287
return -1;
287288

288289
for (p = dest; p < (dest + len); p++) {
@@ -325,16 +326,19 @@ char *git_win32_path_8dot3_name(const char *path)
325326
wchar_t *start;
326327
char *shortname;
327328
int len, namelen = 1;
329+
int max_path_utf16_length = git_win32_longpaths_support
330+
? GIT_WIN_PATH_UTF16
331+
: GIT_WIN_SHORT_PATH_UTF16;
328332

329333
if (git_win32_path_from_utf8(longpath, path) < 0)
330334
return NULL;
331335

332-
len = GetShortPathNameW(longpath, shortpath, GIT_WIN_PATH_UTF16);
336+
len = GetShortPathNameW(longpath, shortpath, max_path_utf16_length);
333337

334338
while (len && shortpath[len-1] == L'\\')
335339
shortpath[--len] = L'\0';
336340

337-
if (len == 0 || len >= GIT_WIN_PATH_UTF16)
341+
if (len == 0 || len >= max_path_utf16_length)
338342
return NULL;
339343

340344
for (start = shortpath + (len - 1);
@@ -370,6 +374,9 @@ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)
370374
DWORD ioctl_ret;
371375
wchar_t *target;
372376
size_t target_len;
377+
size_t max_path_utf16_length = git_win32_longpaths_support
378+
? GIT_WIN_PATH_UTF16
379+
: GIT_WIN_SHORT_PATH_UTF16;
373380

374381
int error = -1;
375382

@@ -416,7 +423,7 @@ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)
416423

417424
/* Need one additional character in the target buffer
418425
* for the terminating NULL. */
419-
if (GIT_WIN_PATH_UTF16 > target_len) {
426+
if (max_path_utf16_length > target_len) {
420427
wcscpy(dest, target);
421428
error = (int)target_len;
422429
}

src/win32/posix_w32.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
unsigned long git_win32__createfile_sharemode =
4646
FILE_SHARE_READ | FILE_SHARE_WRITE;
4747
int git_win32__retries = 10;
48+
extern bool git_win32_longpaths_support;
4849

4950
GIT_INLINE(void) set_errno(void)
5051
{
@@ -636,7 +637,10 @@ int p_futimes(int fd, const struct p_timeval times[2])
636637
int p_getcwd(char *buffer_out, size_t size)
637638
{
638639
git_win32_path buf;
639-
wchar_t *cwd = _wgetcwd(buf, GIT_WIN_PATH_UTF16);
640+
int max_path_utf16_length = git_win32_longpaths_support
641+
? GIT_WIN_PATH_UTF16
642+
: GIT_WIN_SHORT_PATH_UTF16;
643+
wchar_t *cwd = _wgetcwd(buf, max_path_utf16_length);
640644

641645
if (!cwd)
642646
return -1;
@@ -662,6 +666,9 @@ static int getfinalpath_w(
662666
{
663667
HANDLE hFile;
664668
DWORD dwChars;
669+
DWORD max_path_utf16_length = git_win32_longpaths_support
670+
? GIT_WIN_PATH_UTF16
671+
: GIT_WIN_SHORT_PATH_UTF16;
665672

666673
/* Use FILE_FLAG_BACKUP_SEMANTICS so we can open a directory. Do not
667674
* specify FILE_FLAG_OPEN_REPARSE_POINT; we want to open a handle to the
@@ -673,10 +680,10 @@ static int getfinalpath_w(
673680
return -1;
674681

675682
/* Call GetFinalPathNameByHandle */
676-
dwChars = GetFinalPathNameByHandleW(hFile, dest, GIT_WIN_PATH_UTF16, FILE_NAME_NORMALIZED);
683+
dwChars = GetFinalPathNameByHandleW(hFile, dest, max_path_utf16_length, FILE_NAME_NORMALIZED);
677684
CloseHandle(hFile);
678685

679-
if (!dwChars || dwChars >= GIT_WIN_PATH_UTF16)
686+
if (!dwChars || dwChars >= max_path_utf16_length)
680687
return -1;
681688

682689
/* The path may be delivered to us with a namespace prefix; remove */
@@ -779,14 +786,17 @@ int p_rmdir(const char* path)
779786
char *p_realpath(const char *orig_path, char *buffer)
780787
{
781788
git_win32_path orig_path_w, buffer_w;
789+
DWORD max_path_utf16_length = git_win32_longpaths_support
790+
? GIT_WIN_PATH_UTF16
791+
: GIT_WIN_SHORT_PATH_UTF16;
782792

783793
if (git_win32_path_from_utf8(orig_path_w, orig_path) < 0)
784794
return NULL;
785795

786796
/* Note that if the path provided is a relative path, then the current directory
787797
* is used to resolve the path -- which is a concurrency issue because the current
788798
* directory is a process-wide variable. */
789-
if (!GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL)) {
799+
if (!GetFullPathNameW(orig_path_w, max_path_utf16_length, buffer_w, NULL)) {
790800
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
791801
errno = ENAMETOOLONG;
792802
else

src/win32/w32_util.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include "w32_util.h"
99

10+
extern bool git_win32_longpaths_support;
11+
1012
/**
1113
* Creates a FindFirstFile(Ex) filter string from a UTF-8 path.
1214
* The filter string enumerates all items in the directory.
@@ -19,6 +21,9 @@ bool git_win32__findfirstfile_filter(git_win32_path dest, const char *src)
1921
{
2022
static const wchar_t suffix[] = L"\\*";
2123
int len = git_win32_path_from_utf8(dest, src);
24+
size_t max_path_utf16_length = git_win32_longpaths_support
25+
? GIT_WIN_PATH_UTF16
26+
: GIT_WIN_SHORT_PATH_UTF16;
2227

2328
/* Ensure the path was converted */
2429
if (len < 0)
@@ -35,7 +40,7 @@ bool git_win32__findfirstfile_filter(git_win32_path dest, const char *src)
3540
}
3641

3742
/* Ensure we have enough room to add the suffix */
38-
if ((size_t)len >= GIT_WIN_PATH_UTF16 - CONST_STRLEN(suffix))
43+
if ((size_t)len >= max_path_utf16_length - CONST_STRLEN(suffix))
3944
return false;
4045

4146
wcscat(dest, suffix);

0 commit comments

Comments
 (0)
0