1
0
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:
Peter Nelson
2024-07-09 17:10:27 +01:00
committed by Peter Nelson
parent b37954722b
commit e2a796dbcd
8 changed files with 34 additions and 38 deletions

View File

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