From f8bb9d84845be12b3ffb709bf9a26df4f40f898f Mon Sep 17 00:00:00 2001 From: zhenhaonong Date: Fri, 16 Sep 2022 15:55:56 +0800 Subject: [PATCH] Fix socketpair failure when temporary directory has non-latin character --- .github/workflows/build.yml | 6 ++++++ evutil.c | 33 ++++++++++++++++++++------------- test/regress_buffer.c | 14 +++++++++++++- test/regress_main.c | 20 +++++++++++++++----- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 75202705..9a02f263 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -288,6 +288,7 @@ jobs: - DISABLE_DEBUG_MODE - DISABLE_MM_REPLACEMENT - DUNICODE + - UNOCODE_TEMPORARY_DIRECTORY - TEST_EXPORT_SHARED - TEST_EXPORT_STATIC @@ -332,6 +333,11 @@ jobs: elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "UNICODE" ) { $EVENT_CMAKE_OPTIONS="-DCMAKE_C_FLAGS='-DUNICODE -D_UNICODE'" } + elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "UNOCODE_TEMPORARY_DIRECTORY" ) { + $EVENT_CMAKE_OPTIONS="" + mkdir "${{ runner.workspace }}\𝑼𝑡𝑰π‘ͺ𝑢𝑫𝑬" + echo "TMP=${{ runner.workspace }}\𝑼𝑡𝑰π‘ͺ𝑢𝑫𝑬" >> $env:GITHUB_ENV + } elseif ( "${{ matrix.EVENT_MATRIX }}" -eq "TEST_EXPORT_SHARED" ) { $EVENT_CMAKE_OPTIONS="-DEVENT__DISABLE_TESTS=ON -DEVENT__DISABLE_SAMPLES=ON" } diff --git a/evutil.c b/evutil.c index c321eb60..ae862ee1 100644 --- a/evutil.c +++ b/evutil.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef EVENT__HAVE_AFUNIX_H #include #endif @@ -212,14 +213,14 @@ evutil_read_file_(const char *filename, char **content_out, size_t *len_out, #ifdef _WIN32 static int -create_tmpfile(char tmpfile[MAX_PATH]) +create_tmpfile(WCHAR tmpfile[MAX_PATH]) { - char short_path[MAX_PATH] = {0}; - char long_path[MAX_PATH] = {0}; - char prefix[4] = {0}; - // GetTempFileNameA() uses up to the first three characters of the prefix + WCHAR short_path[MAX_PATH] = {0}; + WCHAR long_path[MAX_PATH] = {0}; + WCHAR prefix[4] = {0}; + // GetTempFileNameW() uses up to the first three characters of the prefix // and windows filesystems are case-insensitive - const char *base32set = "abcdefghijklmnopqrstuvwxyz012345"; + const WCHAR *base32set = L"abcdefghijklmnopqrstuvwxyz012345"; ev_uint16_t rnd; evutil_secure_rng_get_bytes(&rnd, sizeof(rnd)); @@ -228,9 +229,9 @@ create_tmpfile(char tmpfile[MAX_PATH]) prefix[2] = base32set[(rnd >> 10) & 31]; prefix[3] = '\0'; - GetTempPathA(MAX_PATH, short_path); - GetLongPathNameA(short_path, long_path, MAX_PATH); - if (!GetTempFileNameA(long_path, prefix, 0, tmpfile)) { + GetTempPathW(MAX_PATH, short_path); + GetLongPathNameW(short_path, long_path, MAX_PATH); + if (!GetTempFileNameW(long_path, prefix, 0, tmpfile)) { event_warnx("GetTempFileName failed: %d", EVUTIL_SOCKET_ERROR()); return -1; } @@ -271,7 +272,8 @@ evutil_win_socketpair_afunix(int family, int type, int protocol, struct sockaddr_un listen_addr; struct sockaddr_un connect_addr; - char tmp_file[MAX_PATH] = {0}; + WCHAR tmp_file[MAX_PATH] = {0}; + char tmp_file_utf8[MAX_PATH] = {0}; ev_socklen_t size; int saved_errno = -1; @@ -289,9 +291,14 @@ evutil_win_socketpair_afunix(int family, int type, int protocol, if (create_tmpfile(tmp_file)) { goto tidy_up_and_fail; } - DeleteFileA(tmp_file); + DeleteFileW(tmp_file); + + /* Windows requires `sun_path` to be encoded by UTF-8 */ + WideCharToMultiByte( + CP_UTF8, 0, tmp_file, MAX_PATH, tmp_file_utf8, MAX_PATH, NULL, NULL); + listen_addr.sun_family = AF_UNIX; - if (strlcpy(listen_addr.sun_path, tmp_file, UNIX_PATH_MAX) >= + if (strlcpy(listen_addr.sun_path, tmp_file_utf8, UNIX_PATH_MAX) >= UNIX_PATH_MAX) { event_warnx("Temp file name is too long"); goto tidy_up_and_fail; @@ -352,7 +359,7 @@ evutil_win_socketpair_afunix(int family, int type, int protocol, if (acceptor != -1) evutil_closesocket(acceptor); if (tmp_file[0]) - DeleteFileA(tmp_file); + DeleteFileW(tmp_file); EVUTIL_SET_SOCKET_ERROR(saved_errno); return -1; diff --git a/test/regress_buffer.c b/test/regress_buffer.c index acd03ee3..5683810e 100644 --- a/test/regress_buffer.c +++ b/test/regress_buffer.c @@ -1199,6 +1199,10 @@ test_evbuffer_add_file(void *ptr) } fd = regress_make_tmpfile(data, datalen, &tmpfilename); + /* On Windows, if TMP environment variable is corrupted, we may not be + * able create temporary file, just skip it */ + if (fd < 0) + tt_skip(); if (map_from_offset) { starting_offset = datalen/4 + 1; @@ -1332,7 +1336,10 @@ test_evbuffer_file_segment_add_cleanup_cb(void* ptr) char const* arg = "token"; fd = regress_make_tmpfile("file_segment_test_file", 22, &tmpfilename); - tt_int_op(fd, >=, 0); + /* On Windows, if TMP environment variable is corrupted, we may not be + * able create temporary file, just skip it */ + if (fd < 0) + tt_skip(); evb = evbuffer_new(); tt_assert(evb); @@ -2587,6 +2594,11 @@ test_evbuffer_freeze(void *ptr) FREEZE_EQ(r, 0, -1); len = strlen(tmpfilecontent); fd = regress_make_tmpfile(tmpfilecontent, len, &tmpfilename); + /* On Windows, if TMP environment variable is corrupted, we may not be + * able create temporary file, just skip it */ + if (fd < 0) + tt_skip(); + r = evbuffer_add_file(buf, fd, 0, len); FREEZE_EQ(r, 0, -1); diff --git a/test/regress_main.c b/test/regress_main.c index 9f0dcaf2..489c74b7 100644 --- a/test/regress_main.c +++ b/test/regress_main.c @@ -152,19 +152,26 @@ regress_make_tmpfile(const void *data, size_t datalen, char **filename_out) return (fd); #else /* XXXX actually delete the file later */ - char tmpfilepath[MAX_PATH]; + WCHAR tmpfilepath[MAX_PATH]; + WCHAR tmpfilelongpath[MAX_PATH]; + WCHAR tmpfilewideame[MAX_PATH]; char tmpfilename[MAX_PATH]; DWORD r, written; int tries = 16; HANDLE h; - r = GetTempPathA(MAX_PATH, tmpfilepath); + r = GetTempPathW(MAX_PATH, tmpfilepath); + if (r > MAX_PATH || r == 0) + return (-1); + r = GetLongPathNameW(tmpfilepath, tmpfilelongpath, MAX_PATH); if (r > MAX_PATH || r == 0) return (-1); for (; tries > 0; --tries) { - r = GetTempFileNameA(tmpfilepath, "LIBEVENT", 0, tmpfilename); - if (r == 0) + r = GetTempFileNameW(tmpfilelongpath, L"LIBEVENT", 0, tmpfilewideame); + if (r == 0) { + int err = GetLastError(); return (-1); - h = CreateFileA(tmpfilename, GENERIC_READ|GENERIC_WRITE, + } + h = CreateFileW(tmpfilewideame, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (h != INVALID_HANDLE_VALUE) break; @@ -172,6 +179,9 @@ regress_make_tmpfile(const void *data, size_t datalen, char **filename_out) if (tries == 0) return (-1); written = 0; + WideCharToMultiByte( + CP_ACP, 0, tmpfilewideame, MAX_PATH, tmpfilename, + MAX_PATH, NULL, NULL); *filename_out = strdup(tmpfilename); WriteFile(h, data, (DWORD)datalen, &written, NULL); /* Closing the fd returned by this function will indeed close h. */