Skip to content

Commit

Permalink
path: use proper size for win32 api calls
Browse files Browse the repository at this point in the history
  • Loading branch information
ianhattendorf committed Jan 10, 2020
1 parent 35656a8 commit 557fd6f
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 10 deletions.
6 changes: 4 additions & 2 deletions src/path.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <stdio.h>
#include <ctype.h>

extern bool git_win32_longpaths_support;

static int dos_drive_prefix_length(const char *path)
{
int i;
Expand Down Expand Up @@ -1253,14 +1255,14 @@ int git_path_diriter_init(
static int diriter_update_paths(git_path_diriter *diriter)
{
size_t filename_len, path_len;

size_t max_path_length = git_win32_longpaths_support ? GIT_WIN_PATH_UTF16 : GIT_WIN_SHORT_PATH_UTF16;
filename_len = wcslen(diriter->current.cFileName);

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

if (path_len > GIT_WIN_PATH_UTF16) {
if (path_len > max_path_length) {
git_error_set(GIT_ERROR_FILESYSTEM,
"invalid path '%.*ls\\%ls' (path too long)",
diriter->parent_len, diriter->path, diriter->current.cFileName);
Expand Down
8 changes: 5 additions & 3 deletions src/win32/path_w32.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,16 +298,17 @@ char *git_win32_path_8dot3_name(const char *path)
wchar_t *start;
char *shortname;
int len, namelen = 1;
int max_path_length = git_win32_longpaths_support ? GIT_WIN_PATH_UTF16 : GIT_WIN_SHORT_PATH_UTF16;

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

len = GetShortPathNameW(longpath, shortpath, GIT_WIN_PATH_UTF16);
len = GetShortPathNameW(longpath, shortpath, max_path_length);

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

if (len == 0 || len >= GIT_WIN_PATH_UTF16)
if (len == 0 || len >= max_path_length)
return NULL;

for (start = shortpath + (len - 1);
Expand Down Expand Up @@ -343,6 +344,7 @@ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)
DWORD ioctl_ret;
wchar_t *target;
size_t target_len;
size_t max_path_length = git_win32_longpaths_support ? GIT_WIN_PATH_UTF16 : GIT_WIN_SHORT_PATH_UTF16;

int error = -1;

Expand Down Expand Up @@ -389,7 +391,7 @@ int git_win32_path_readlink_w(git_win32_path dest, const git_win32_path path)

/* Need one additional character in the target buffer
* for the terminating NULL. */
if (GIT_WIN_PATH_UTF16 > target_len) {
if (max_path_length > target_len) {
wcscpy(dest, target);
error = (int)target_len;
}
Expand Down
12 changes: 8 additions & 4 deletions src/win32/posix_w32.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
unsigned long git_win32__createfile_sharemode =
FILE_SHARE_READ | FILE_SHARE_WRITE;
int git_win32__retries = 10;
extern bool git_win32_longpaths_support;

GIT_INLINE(void) set_errno(void)
{
Expand Down Expand Up @@ -630,7 +631,8 @@ int p_futimes(int fd, const struct p_timeval times[2])
int p_getcwd(char *buffer_out, size_t size)
{
git_win32_path buf;
wchar_t *cwd = _wgetcwd(buf, GIT_WIN_PATH_UTF16);
size_t max_path_length = git_win32_longpaths_support ? GIT_WIN_PATH_UTF16 : GIT_WIN_SHORT_PATH_UTF16;
wchar_t *cwd = _wgetcwd(buf, max_path_length);

if (!cwd)
return -1;
Expand All @@ -656,6 +658,7 @@ static int getfinalpath_w(
{
HANDLE hFile;
DWORD dwChars;
size_t max_path_length = git_win32_longpaths_support ? GIT_WIN_PATH_UTF16 : GIT_WIN_SHORT_PATH_UTF16;

/* Use FILE_FLAG_BACKUP_SEMANTICS so we can open a directory. Do not
* specify FILE_FLAG_OPEN_REPARSE_POINT; we want to open a handle to the
Expand All @@ -667,10 +670,10 @@ static int getfinalpath_w(
return -1;

/* Call GetFinalPathNameByHandle */
dwChars = GetFinalPathNameByHandleW(hFile, dest, GIT_WIN_PATH_UTF16, FILE_NAME_NORMALIZED);
dwChars = GetFinalPathNameByHandleW(hFile, dest, max_path_length, FILE_NAME_NORMALIZED);
CloseHandle(hFile);

if (!dwChars || dwChars >= GIT_WIN_PATH_UTF16)
if (!dwChars || dwChars >= max_path_length)
return -1;

/* The path may be delivered to us with a namespace prefix; remove */
Expand Down Expand Up @@ -773,14 +776,15 @@ int p_rmdir(const char* path)
char *p_realpath(const char *orig_path, char *buffer)
{
git_win32_path orig_path_w, buffer_w;
size_t max_path_length = git_win32_longpaths_support ? GIT_WIN_PATH_UTF16 : GIT_WIN_SHORT_PATH_UTF16;

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

/* Note that if the path provided is a relative path, then the current directory
* is used to resolve the path -- which is a concurrency issue because the current
* directory is a process-wide variable. */
if (!GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL)) {
if (!GetFullPathNameW(orig_path_w, max_path_length, buffer_w, NULL)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
errno = ENAMETOOLONG;
else
Expand Down
5 changes: 4 additions & 1 deletion src/win32/w32_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include "w32_util.h"

extern bool git_win32_longpaths_support;

/**
* Creates a FindFirstFile(Ex) filter string from a UTF-8 path.
* The filter string enumerates all items in the directory.
Expand All @@ -19,6 +21,7 @@ bool git_win32__findfirstfile_filter(git_win32_path dest, const char *src)
{
static const wchar_t suffix[] = L"\\*";
int len = git_win32_path_from_utf8(dest, src);
size_t max_path_length = git_win32_longpaths_support ? GIT_WIN_PATH_UTF16 : GIT_WIN_SHORT_PATH_UTF16;

/* Ensure the path was converted */
if (len < 0)
Expand All @@ -35,7 +38,7 @@ bool git_win32__findfirstfile_filter(git_win32_path dest, const char *src)
}

/* Ensure we have enough room to add the suffix */
if ((size_t)len >= GIT_WIN_PATH_UTF16 - CONST_STRLEN(suffix))
if ((size_t)len >= max_path_length - CONST_STRLEN(suffix))
return false;

wcscat(dest, suffix);
Expand Down

0 comments on commit 557fd6f

Please sign in to comment.