4377: Fix incorrect/inconsistent buffer sizes, improve fs_is_dir, cleanup r=def- a=Robyt3

- Fix buffers sizes when using `MultiByteToWideChar` and `WideCharToMultiByte`.
   - input length is now always `-1`, as this will assume null-termination and also ensure it for the output
   - output length is the number of array elements (and not the size in bytes as previously specified in some cases)
- Use `str_format` in `fs_storage_path` instead of platform specific functions for better maintainability.
- Implement `fs_is_dir` smarter by using `GetFileAttributesW` on Windows.
- Remove unused `fs_getmtime` that does not work with unicode on Windows in favor of the existing more generalized `fs_file_time`.

## Checklist

- [x] Tested the change ingame
- [ ] Provided screenshots if it is a visual change
- [ ] Tested in combination with possibly related configuration options
- [ ] Written a unit test if it works standalone, system.c especially
- [ ] Considered possible null pointers and out of bounds array indexing
- [ ] Changed no physics that affect existing maps
- [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional)


Co-authored-by: Robert Müller <robert.mueller@uni-siegen.de>
This commit is contained in:
bors[bot] 2021-11-21 10:39:41 +00:00 committed by GitHub
commit c18d4f8254
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 53 deletions

View file

@ -164,7 +164,7 @@ static void logger_win_debugger(const char *line, void *user)
{
(void)user;
WCHAR wBuffer[512];
MultiByteToWideChar(CP_UTF8, 0, line, -1, wBuffer, sizeof(wBuffer));
MultiByteToWideChar(CP_UTF8, 0, line, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
OutputDebugStringW(wBuffer);
OutputDebugStringW(L"\n");
}
@ -316,7 +316,7 @@ IOHANDLE io_open(const char *filename, int flags)
dbg_assert(flags == IOFLAG_READ || flags == IOFLAG_WRITE || flags == IOFLAG_APPEND, "flags must be read, write or append");
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, filename, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, filename, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
if(flags == IOFLAG_READ)
return (IOHANDLE)_wfsopen(wBuffer, L"rb", _SH_DENYNO);
if(flags == IOFLAG_WRITE)
@ -1452,7 +1452,7 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
int error = WSAGetLastError();
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
wBuffer[0] = 0;
WideCharToMultiByte(CP_UTF8, 0, wBuffer, sizeof(wBuffer), buf, sizeof(buf), NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buf, sizeof(buf), NULL, NULL);
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
#else
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
@ -1491,7 +1491,7 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
int error = WSAGetLastError();
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
wBuffer[0] = 0;
WideCharToMultiByte(CP_UTF8, 0, wBuffer, sizeof(wBuffer), buf, sizeof(buf), NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buf, sizeof(buf), NULL, NULL);
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
#else
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
@ -2060,7 +2060,7 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
int length;
str_format(buffer, sizeof(buffer), "%s/*", dir);
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
handle = FindFirstFileW(wBuffer, &finddata);
if(handle == INVALID_HANDLE_VALUE)
@ -2072,7 +2072,7 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
/* add all the entries */
do
{
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, IO_MAX_PATH_LENGTH, NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, sizeof(buffer2), NULL, NULL);
str_copy(buffer + length, buffer2, (int)sizeof(buffer) - length);
if(cb(buffer2, fs_is_dir(buffer), type, user))
break;
@ -2114,7 +2114,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
int length;
str_format(buffer, sizeof(buffer), "%s/*", dir);
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
handle = FindFirstFileW(wBuffer, &finddata);
if(handle == INVALID_HANDLE_VALUE)
@ -2126,7 +2126,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
/* add all the entries */
do
{
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, IO_MAX_PATH_LENGTH, NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, sizeof(buffer2), NULL, NULL);
str_copy(buffer + length, buffer2, (int)sizeof(buffer) - length);
CFsFileInfo info;
@ -2179,17 +2179,14 @@ int fs_storage_path(const char *appname, char *path, int max)
if(!home)
return -1;
char buffer[IO_MAX_PATH_LENGTH];
WideCharToMultiByte(CP_UTF8, 0, home, -1, buffer, IO_MAX_PATH_LENGTH, NULL, NULL);
_snprintf(path, max, "%s/%s", buffer, appname);
WideCharToMultiByte(CP_UTF8, 0, home, -1, buffer, sizeof(buffer), NULL, NULL);
str_format(path, max, "%s/%s", buffer, appname);
return 0;
#elif defined(CONF_PLATFORM_ANDROID)
// just use the data directory
return -1;
#else
char *home = getenv("HOME");
#if !defined(CONF_PLATFORM_MACOS)
int i;
#endif
if(!home)
return -1;
@ -2199,10 +2196,10 @@ int fs_storage_path(const char *appname, char *path, int max)
#endif
#if defined(CONF_PLATFORM_MACOS)
snprintf(path, max, "%s/Library/Application Support/%s", home, appname);
str_format(path, max, "%s/Library/Application Support/%s", home, appname);
#else
snprintf(path, max, "%s/.%s", home, appname);
for(i = str_length(home) + 2; path[i]; i++)
str_format(path, max, "%s/.%s", home, appname);
for(int i = str_length(home) + 2; path[i]; i++)
path[i] = tolower((unsigned char)path[i]);
#endif
@ -2232,7 +2229,7 @@ int fs_makedir(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
if(_wmkdir(wBuffer) == 0)
return 0;
if(errno == EEXIST)
@ -2256,7 +2253,7 @@ int fs_removedir(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wPath[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, path, IO_MAX_PATH_LENGTH, wPath, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, sizeof(wPath) / sizeof(WCHAR));
if(RemoveDirectoryW(wPath) != 0)
return 0;
return -1;
@ -2270,18 +2267,10 @@ int fs_removedir(const char *path)
int fs_is_dir(const char *path)
{
#if defined(CONF_FAMILY_WINDOWS)
/* TODO: do this smarter */
WIN32_FIND_DATAW finddata;
HANDLE handle;
char buffer[IO_MAX_PATH_LENGTH];
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
str_format(buffer, sizeof(buffer), "%s/*", path);
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
if((handle = FindFirstFileW(wBuffer, &finddata)) == INVALID_HANDLE_VALUE)
return 0;
FindClose(handle);
return 1;
WCHAR wPath[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, sizeof(wPath) / sizeof(WCHAR));
DWORD attributes = GetFileAttributesW(wPath);
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
#else
struct stat sb;
if(stat(path, &sb) == -1)
@ -2290,22 +2279,13 @@ int fs_is_dir(const char *path)
#endif
}
time_t fs_getmtime(const char *path)
{
struct stat sb;
if(stat(path, &sb) == -1)
return 0;
return sb.st_mtime;
}
int fs_chdir(const char *path)
{
if(fs_is_dir(path))
{
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
if(_wchdir(wBuffer))
return 1;
else
@ -2329,7 +2309,7 @@ char *fs_getcwd(char *buffer, int buffer_size)
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
if(_wgetcwd(wBuffer, buffer_size) == 0)
return 0;
WideCharToMultiByte(CP_UTF8, 0, wBuffer, IO_MAX_PATH_LENGTH, buffer, buffer_size, NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buffer, buffer_size, NULL, NULL);
return buffer;
#else
return getcwd(buffer, buffer_size);
@ -2357,7 +2337,7 @@ int fs_remove(const char *filename)
{
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wFilename[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, filename, IO_MAX_PATH_LENGTH, wFilename, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, filename, -1, wFilename, sizeof(wFilename) / sizeof(WCHAR));
return DeleteFileW(wFilename) == 0;
#else
return unlink(filename) != 0;
@ -2369,8 +2349,8 @@ int fs_rename(const char *oldname, const char *newname)
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wOldname[IO_MAX_PATH_LENGTH];
WCHAR wNewname[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, oldname, IO_MAX_PATH_LENGTH, wOldname, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, newname, IO_MAX_PATH_LENGTH, wNewname, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, oldname, -1, wOldname, sizeof(wOldname) / sizeof(WCHAR));
MultiByteToWideChar(CP_UTF8, 0, newname, -1, wNewname, sizeof(wNewname) / sizeof(WCHAR));
if(MoveFileExW(wOldname, wNewname, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) == 0)
return 1;
#else
@ -2387,7 +2367,7 @@ int fs_file_time(const char *name, time_t *created, time_t *modified)
HANDLE handle;
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
MultiByteToWideChar(CP_UTF8, 0, name, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
MultiByteToWideChar(CP_UTF8, 0, name, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
handle = FindFirstFileW(wBuffer, &finddata);
if(handle == INVALID_HANDLE_VALUE)
return 1;
@ -3566,7 +3546,7 @@ PROCESS shell_execute(const char *file)
{
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wBuffer[512];
MultiByteToWideChar(CP_UTF8, 0, file, -1, wBuffer, sizeof(wBuffer));
MultiByteToWideChar(CP_UTF8, 0, file, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
SHELLEXECUTEINFOW info;
mem_zero(&info, sizeof(SHELLEXECUTEINFOW));
info.cbSize = sizeof(SHELLEXECUTEINFOW);
@ -3610,7 +3590,7 @@ int open_link(const char *link)
{
#if defined(CONF_FAMILY_WINDOWS)
WCHAR wBuffer[512];
MultiByteToWideChar(CP_UTF8, 0, link, -1, wBuffer, sizeof(wBuffer));
MultiByteToWideChar(CP_UTF8, 0, link, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
return (uintptr_t)ShellExecuteW(NULL, L"open", wBuffer, NULL, NULL, SW_SHOWDEFAULT) > 32;
#elif defined(CONF_PLATFORM_LINUX)
char aBuf[512];

View file

@ -1689,12 +1689,6 @@ int fs_storage_path(const char *appname, char *path, int max);
*/
int fs_is_dir(const char *path);
/*
Function: fs_getmtime
Gets the modification time of a file
*/
time_t fs_getmtime(const char *path);
/*
Function: fs_chdir
Changes current working directory