Fix socketpair failure when temporary directory has non-latin character
authorzhenhaonong <zhenhaonong@tencent.com>
Fri, 16 Sep 2022 07:55:56 +0000 (15:55 +0800)
committerAzat Khuzhin <a3at.mail@gmail.com>
Mon, 26 Sep 2022 18:43:21 +0000 (21:43 +0300)
.github/workflows/build.yml
evutil.c
test/regress_buffer.c
test/regress_main.c

index 7520270597fd8e3756a6acbc436a859493482932..9a02f2633121953cbe5c689bffb6333ebfbb1e9d 100644 (file)
@@ -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"
           }
index c321eb60fe82badf1e389e70eed5c66389e1cf9d..ae862ee104b6f4588fb1bdfbf388a91468751a48 100644 (file)
--- a/evutil.c
+++ b/evutil.c
@@ -31,6 +31,7 @@
 #include <winsock2.h>
 #include <winerror.h>
 #include <ws2tcpip.h>
+#include <stringapiset.h>
 #ifdef EVENT__HAVE_AFUNIX_H
 #include <afunix.h>
 #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;
index acd03ee3a17993cea2bfd2bd2dcb76e1a84301d5..5683810e263a83d77146c5596f63001dcaf2505e 100644 (file)
@@ -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);
 
index 9f0dcaf284885f466fa26653bf9a8d55f55c1e1e..489c74b733bd0ac9b05201506661175e8321b298 100644 (file)
@@ -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. */