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

Skip to content

Commit e24949b

Browse files
committed
path: use proper size for win32 api calls
1 parent d62cca7 commit e24949b

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;
@@ -1253,14 +1255,16 @@ int git_path_diriter_init(
12531255
static int diriter_update_paths(git_path_diriter *diriter)
12541256
{
12551257
size_t filename_len, path_len;
1256-
1258+
size_t max_path_utf16_length = git_win32_longpaths_support
1259+
? GIT_WIN_PATH_UTF16
1260+
: GIT_WIN_SHORT_PATH_UTF16;
12571261
filename_len = wcslen(diriter->current.cFileName);
12581262

12591263
if (GIT_ADD_SIZET_OVERFLOW(&path_len, diriter->parent_len, filename_len) ||
12601264
GIT_ADD_SIZET_OVERFLOW(&path_len, path_len, 2))
12611265
return -1;
12621266

1263-
if (path_len > GIT_WIN_PATH_UTF16) {
1267+
if (path_len > max_path_utf16_length) {
12641268
git_error_set(GIT_ERROR_FILESYSTEM,
12651269
"invalid path '%.*ls\\%ls' (path too long)",
12661270
diriter->parent_len, diriter->path, diriter->current.cFileName);

src/win32/path_w32.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ int git_win32_path_canonicalize(git_win32_path path)
8585
{
8686
wchar_t *base, *from, *to, *next;
8787
size_t len;
88-
size_t max_path_length = git_win32_longpaths_support
89-
? GIT_WIN_PATH_UTF16
90-
: GIT_WIN_SHORT_PATH_UTF16;
9188

9289
base = to = path__skip_prefix(path);
9390

@@ -144,22 +141,20 @@ int git_win32_path_canonicalize(git_win32_path path)
144141
while (to > base && to[-1] == L'\\') to--;
145142

146143
*to = L'\0';
147-
len = to - path;
148-
if (len >= 8 && wcsncmp(L"\\\\?\\UNC\\", path, 8) != 0) {
149-
/* Not a UNC path, max length shorter by 2 */
150-
max_path_length -= 2;
151-
}
152-
if (len >= max_path_length) {
144+
if ((to - path) > INT_MAX) {
153145
SetLastError(ERROR_FILENAME_EXCED_RANGE);
154146
return -1;
155147
}
156148

157-
return (int)len;
149+
return (int)(to - path);
158150
}
159151

160152
int git_win32_path__cwd(wchar_t *out, size_t len)
161153
{
162154
int cwd_len;
155+
int max_path_length = git_win32_longpaths_support
156+
? WIN_GIT_PATH_MAX
157+
: WIN_GIT_SHORT_PATH_MAX;
163158

164159
if (len > INT_MAX) {
165160
errno = ENAMETOOLONG;
@@ -176,7 +171,7 @@ int git_win32_path__cwd(wchar_t *out, size_t len)
176171
* '\'s, but we we add a 'UNC' specifier to the path, plus
177172
* a trailing directory separator, plus a NUL.
178173
*/
179-
if (cwd_len > WIN_GIT_PATH_MAX - 4) {
174+
if (cwd_len > max_path_length - 4) {
180175
errno = ENAMETOOLONG;
181176
return -1;
182177
}
@@ -193,7 +188,7 @@ int git_win32_path__cwd(wchar_t *out, size_t len)
193188
* working directory. (One character for the directory separator,
194189
* one for the null.
195190
*/
196-
else if (cwd_len > WIN_GIT_PATH_MAX - 2) {
191+
else if (cwd_len > max_path_length - 2) {
197192
errno = ENAMETOOLONG;
198193
return -1;
199194
}
@@ -204,20 +199,23 @@ int git_win32_path__cwd(wchar_t *out, size_t len)
204199
int git_win32_path_from_utf8(git_win32_path out, const char *src)
205200
{
206201
wchar_t *dest = out;
202+
size_t max_path_length = git_win32_longpaths_support
203+
? WIN_GIT_PATH_MAX
204+
: WIN_GIT_SHORT_PATH_MAX;
207205

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

212210
/* See if this is an absolute path (beginning with a drive letter) */
213211
if (git_path_is_absolute(src)) {
214-
if (git__utf8_to_16(dest, WIN_GIT_PATH_MAX, src) < 0)
212+
if (git__utf8_to_16(dest, max_path_length, src) < 0)
215213
goto on_error;
216214
}
217215
/* File-prefixed NT-style paths beginning with \\?\ */
218216
else if (path__is_nt_namespace(src)) {
219217
/* Skip the NT prefix, the destination already contains it */
220-
if (git__utf8_to_16(dest, WIN_GIT_PATH_MAX, src + PATH__NT_NAMESPACE_LEN) < 0)
218+
if (git__utf8_to_16(dest, max_path_length, src + PATH__NT_NAMESPACE_LEN) < 0)
221219
goto on_error;
222220
}
223221
/* UNC paths */
@@ -226,12 +224,12 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
226224
dest += 4;
227225

228226
/* Skip the leading "\\" */
229-
if (git__utf8_to_16(dest, WIN_GIT_PATH_MAX - 2, src + 2) < 0)
227+
if (git__utf8_to_16(dest, max_path_length - 2, src + 2) < 0)
230228
goto on_error;
231229
}
232230
/* Absolute paths omitting the drive letter */
233231
else if (src[0] == '\\' || src[0] == '/') {
234-
if (path__cwd(dest, WIN_GIT_PATH_MAX) < 0)
232+
if (path__cwd(dest, (int)max_path_length) < 0)
235233
goto on_error;
236234

237235
if (!git_path_is_absolute(dest)) {
@@ -240,19 +238,19 @@ int git_win32_path_from_utf8(git_win32_path out, const char *src)
240238
}
241239

242240
/* Skip the drive letter specification ("C:") */
243-
if (git__utf8_to_16(dest + 2, WIN_GIT_PATH_MAX - 2, src) < 0)
241+
if (git__utf8_to_16(dest + 2, max_path_length - 2, src) < 0)
244242
goto on_error;
245243
}
246244
/* Relative paths */
247245
else {
248246
int cwd_len;
249247

250-
if ((cwd_len = git_win32_path__cwd(dest, WIN_GIT_PATH_MAX)) < 0)
248+
if ((cwd_len = git_win32_path__cwd(dest, max_path_length)) < 0)
251249
goto on_error;
252250

253251
dest[cwd_len++] = L'\\';
254252

255-
if (git__utf8_to_16(dest + cwd_len, WIN_GIT_PATH_MAX - cwd_len, src) < 0)
253+
if (git__utf8_to_16(dest + cwd_len, max_path_length - cwd_len, src) < 0)
256254
goto on_error;
257255
}
258256

@@ -298,16 +296,19 @@ char *git_win32_path_8dot3_name(const char *path)
298296
wchar_t *start;
299297
char *shortname;
300298
int len, namelen = 1;
299+
int max_path_utf16_length = git_win32_longpaths_support
300+
? GIT_WIN_PATH_UTF16
301+
: GIT_WIN_SHORT_PATH_UTF16;
301302

302303
if (git_win32_path_from_utf8(longpath, path) < 0)
303304
return NULL;
304305

305-
len = GetShortPathNameW(longpath, shortpath, GIT_WIN_PATH_UTF16);
306+
len = GetShortPathNameW(longpath, shortpath, max_path_utf16_length);
306307

307308
while (len && shortpath[len-1] == L'\\')
308309
shortpath[--len] = L'\0';
309310

310-
if (len == 0 || len >= GIT_WIN_PATH_UTF16)
311+
if (len == 0 || len >= max_path_utf16_length)
311312
return NULL;
312313

313314
for (start = shortpath + (len - 1);
@@ -343,6 +344,9 @@ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)
343344
DWORD ioctl_ret;
344345
wchar_t *target;
345346
size_t target_len;
347+
size_t max_path_utf16_length = git_win32_longpaths_support
348+
? < F438 span class=pl-c1>GIT_WIN_PATH_UTF16
349+
: GIT_WIN_SHORT_PATH_UTF16;
346350

347351
int error = -1;
348352

@@ -389,7 +393,7 @@ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)
389393

390394
/* Need one additional character in the target buffer
391395
* for the terminating NULL. */
392-
if (GIT_WIN_PATH_UTF16 > target_len) {
396+
if (max_path_utf16_length > target_len) {
393397
wcscpy(dest, target);
394398
error = (int)target_len;
395399
}

src/win32/posix_w32.c

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
unsigned long git_win32__createfile_sharemode =
4747
FILE_SHARE_READ | FILE_SHARE_WRITE;
4848
int git_win32__retries = 10;
49+
extern bool git_win32_longpaths_support;
4950

5051
GIT_INLINE(void) set_errno(void)
5152
{
@@ -438,6 +439,9 @@ int p_symlink(const char *target, const char *path)
438439
{
439440
git_win32_path target_w, path_w;
440441
DWORD dwFlags;
442+
size_t max_path_length = git_win32_longpaths_support
443+
? WIN_GIT_PATH_MAX
444+
: WIN_GIT_SHORT_PATH_MAX;
441445

442446
/*
443447
* Convert both target and path to Windows-style paths. Note that we do
@@ -447,7 +451,7 @@ int p_symlink(const char *target, const char *path)
447451
* relative symlinks, this is not someting we want.
448452
*/
449453
if (git_win32_path_from_utf8(path_w, path) < 0 ||
450-
git__utf8_to_16(target_w, WIN_GIT_PATH_MAX, target) < 0 ||
454+
git__utf8_to_16(target_w, max_path_length, target) < 0 ||
451455
git_win32_path_canonicalize(target_w) < 0)
452456
return -1;
453457

@@ -638,7 +642,10 @@ int p_futimes(int fd, const struct p_timeval times[2])
638642
int p_getcwd(char *buffer_out, size_t size)
639643
{
640644
git_win32_path buf;
641-
wchar_t *cwd = _wgetcwd(buf, GIT_WIN_PATH_UTF16);
645+
int max_path_utf16_length = git_win32_longpaths_support
646+
? GIT_WIN_PATH_UTF16
647+
: GIT_WIN_SHORT_PATH_UTF16;
648+
wchar_t *cwd = _wgetcwd(buf, max_path_utf16_length);
642649

643650
if (!cwd)
644651
return -1;
@@ -664,6 +671,9 @@ static int getfinalpath_w(
664671
{
665672
HANDLE hFile;
666673
DWORD dwChars;
674+
DWORD max_path_utf16_length = git_win32_longpaths_support
675+
? GIT_WIN_PATH_UTF16
676+
: GIT_WIN_SHORT_PATH_UTF16;
667677

668678
/* Use FILE_FLAG_BACKUP_SEMANTICS so we can open a directory. Do not
669679
* specify FILE_FLAG_OPEN_REPARSE_POINT; we want to open a handle to the
@@ -675,10 +685,10 @@ static int getfinalpath_w(
675685
return -1;
676686

677687
/* Call GetFinalPathNameByHandle */
678-
dwChars = GetFinalPathNameByHandleW(hFile, dest, GIT_WIN_PATH_UTF16, FILE_NAME_NORMALIZED);
688+
dwChars = GetFinalPathNameByHandleW(hFile, dest, max_path_utf16_length, FILE_NAME_NORMALIZED);
679689
CloseHandle(hFile);
680690

681-
if (!dwChars || dwChars >= GIT_WIN_PATH_UTF16)
691+
if (!dwChars || dwChars >= max_path_utf16_length)
682692
return -1;
683693

684694
/* The path may be delivered to us with a namespace prefix; remove */
@@ -781,14 +791,17 @@ int p_rmdir(const char* path)
781791
char *p_realpath(const char *orig_path, char *buffer)
782792
{
783793
git_win32_path orig_path_w, buffer_w;
794+
DWORD max_path_utf16_length = git_win32_longpaths_support
795+
? GIT_WIN_PATH_UTF16
796+
: GIT_WIN_SHORT_PATH_UTF16;
784797

785798
if (git_win32_path_from_utf8(orig_path_w, orig_path) < 0)
786799
return NULL;
787800

788801
/* Note that if the path provided is a relative path, then the current directory
789802
* is used to resolve the path -- which is a concurrency issue because the current
790803
* directory is a process-wide variable. */
791-
if (!GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL)) {
804+
if (!GetFullPathNameW(orig_path_w, max_path_utf16_length, buffer_w, NULL)) {
792805
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
793806
errno = ENAMETOOLONG;
794807
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 325D - 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