Fix socketpair failure when temporary directory has non-latin character

This commit is contained in:
zhenhaonong 2022-09-16 15:55:56 +08:00 committed by Azat Khuzhin
parent 211c6653ae
commit f8bb9d8484
4 changed files with 54 additions and 19 deletions

View 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"
}

View File

@ -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;

View 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);

View 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. */