mirror of
https://github.com/OpenTTD/OpenTTD
synced 2026-01-29 07:04:35 +01:00
Codefix: Potential unterminated string returned from convert_to_fs.
Converting from UTF-8 to UTF-16 could have resulted in a buffer overflow if the buffer size was exactly the length of the converted string. Pass string_view/span to convert_from/to_fs instead, and ensure the buffer is terminated. This replaces passing a pointer to the buffer and the buffer size as separate parameters, allowing the compiler to pass both in one parameter. Removes use of `lengthof()`.
This commit is contained in:
committed by
Peter Nelson
parent
b37954722b
commit
e2a796dbcd
@@ -225,7 +225,7 @@ char *getcwd(char *buf, size_t size)
|
||||
{
|
||||
wchar_t path[MAX_PATH];
|
||||
GetCurrentDirectory(MAX_PATH - 1, path);
|
||||
convert_from_fs(path, buf, size);
|
||||
convert_from_fs(path, {buf, size});
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ void DetermineBasePaths(const char *exe)
|
||||
} else {
|
||||
/* Use the folder of the config file as working directory. */
|
||||
wchar_t config_dir[MAX_PATH];
|
||||
convert_to_fs(_config_file, path, lengthof(path));
|
||||
convert_to_fs(_config_file, path);
|
||||
if (!GetFullPathName(path, static_cast<DWORD>(std::size(config_dir)), config_dir, nullptr)) {
|
||||
Debug(misc, 0, "GetFullPathName failed ({})", GetLastError());
|
||||
_searchpaths[SP_WORKING_DIR].clear();
|
||||
@@ -292,7 +292,7 @@ void DetermineBasePaths(const char *exe)
|
||||
_searchpaths[SP_BINARY_DIR].clear();
|
||||
} else {
|
||||
wchar_t exec_dir[MAX_PATH];
|
||||
convert_to_fs(exe, path, std::size(path));
|
||||
convert_to_fs(exe, path);
|
||||
if (!GetFullPathName(path, static_cast<DWORD>(std::size(exec_dir)), exec_dir, nullptr)) {
|
||||
Debug(misc, 0, "GetFullPathName failed ({})", GetLastError());
|
||||
_searchpaths[SP_BINARY_DIR].clear();
|
||||
@@ -365,37 +365,33 @@ std::wstring OTTD2FS(const std::string &name)
|
||||
/**
|
||||
* Convert to OpenTTD's encoding from that of the environment in
|
||||
* UNICODE. OpenTTD encoding is UTF8, local is wide.
|
||||
* @param name pointer to a valid string that will be converted
|
||||
* @param utf8_buf pointer to a valid buffer that will receive the converted string
|
||||
* @param buflen length in characters of the receiving buffer
|
||||
* @return pointer to utf8_buf. If conversion fails the string is of zero-length
|
||||
* @param src wide string that will be converted
|
||||
* @param dst_buf span of valid char buffer that will receive the converted string
|
||||
* @return pointer to dst_buf. If conversion fails the string is of zero-length
|
||||
*/
|
||||
char *convert_from_fs(const wchar_t *name, char *utf8_buf, size_t buflen)
|
||||
char *convert_from_fs(const std::wstring_view src, std::span<char> dst_buf)
|
||||
{
|
||||
/* Convert UTF-16 string to UTF-8. */
|
||||
int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, utf8_buf, (int)buflen, nullptr, nullptr);
|
||||
if (len == 0) utf8_buf[0] = '\0';
|
||||
int len = WideCharToMultiByte(CP_UTF8, 0, src.data(), static_cast<int>(src.size()), dst_buf.data(), static_cast<int>(dst_buf.size() - 1U), nullptr, nullptr);
|
||||
dst_buf[len] = '\0';
|
||||
|
||||
return utf8_buf;
|
||||
return dst_buf.data();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert from OpenTTD's encoding to that of the environment in
|
||||
* UNICODE. OpenTTD encoding is UTF8, local is wide.
|
||||
* @param name pointer to a valid string that will be converted
|
||||
* @param system_buf pointer to a valid wide-char buffer that will receive the
|
||||
* converted string
|
||||
* @param buflen length in wide characters of the receiving buffer
|
||||
* @param console_cp convert to the console encoding instead of the normal system encoding.
|
||||
* @return pointer to system_buf. If conversion fails the string is of zero-length
|
||||
* @param src string that will be converted
|
||||
* @param dst_buf span of valid wide-char buffer that will receive the converted string
|
||||
* @return pointer to dst_buf. If conversion fails the string is of zero-length
|
||||
*/
|
||||
wchar_t *convert_to_fs(const std::string_view name, wchar_t *system_buf, size_t buflen)
|
||||
wchar_t *convert_to_fs(const std::string_view src, std::span<wchar_t> dst_buf)
|
||||
{
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, name.data(), (int)name.size(), system_buf, (int)buflen);
|
||||
system_buf[len] = '\0';
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, src.data(), static_cast<int>(src.size()), dst_buf.data(), static_cast<int>(dst_buf.size() - 1U));
|
||||
dst_buf[len] = '\0';
|
||||
|
||||
return system_buf;
|
||||
return dst_buf.data();
|
||||
}
|
||||
|
||||
/** Determine the current user's locale. */
|
||||
@@ -472,8 +468,8 @@ int OTTDStringCompare(std::string_view s1, std::string_view s2)
|
||||
}
|
||||
|
||||
wchar_t s1_buf[512], s2_buf[512];
|
||||
convert_to_fs(s1, s1_buf, lengthof(s1_buf));
|
||||
convert_to_fs(s2, s2_buf, lengthof(s2_buf));
|
||||
convert_to_fs(s1, s1_buf);
|
||||
convert_to_fs(s2, s2_buf);
|
||||
|
||||
return CompareString(MAKELCID(_current_language->winlangid, SORT_DEFAULT), NORM_IGNORECASE, s1_buf, -1, s2_buf, -1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user