mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-04 13:42:55 +01:00
Prevent invalid access in malformed objects
This commit is contained in:
committed by
Ted John
parent
c3035b7601
commit
3aa0eb9bcd
@@ -142,12 +142,12 @@ static wchar_t convert_specific_language_character_to_unicode(int languageId, wc
|
||||
}
|
||||
}
|
||||
|
||||
static utf8 * convert_multibyte_charset(const char * src, int languageId)
|
||||
static utf8 * convert_multibyte_charset(const char * src, size_t srcMaxSize, int languageId)
|
||||
{
|
||||
constexpr char CODEPOINT_DOUBLEBYTE = (char)0xFF;
|
||||
|
||||
auto sb = StringBuilder(64);
|
||||
for (const char * ch = src; *ch != 0;)
|
||||
for (const char * ch = src; (ch < src + srcMaxSize) && (*ch != 0);)
|
||||
{
|
||||
if (*ch == CODEPOINT_DOUBLEBYTE)
|
||||
{
|
||||
@@ -181,15 +181,15 @@ static bool rct2_language_is_multibyte_charset(int languageId)
|
||||
}
|
||||
}
|
||||
|
||||
utf8 *rct2_language_string_to_utf8(const char *src, int languageId)
|
||||
utf8 *rct2_language_string_to_utf8(const char *src, size_t srcSize, int languageId)
|
||||
{
|
||||
if (rct2_language_is_multibyte_charset(languageId))
|
||||
{
|
||||
return convert_multibyte_charset(src, languageId);
|
||||
return convert_multibyte_charset(src, srcSize, languageId);
|
||||
}
|
||||
else
|
||||
{
|
||||
return win1252_to_utf8_alloc(src);
|
||||
return win1252_to_utf8_alloc(src, srcSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ int utf8_length(const utf8 *text);
|
||||
wchar_t *utf8_to_widechar(const utf8 *src);
|
||||
utf8 *widechar_to_utf8(const wchar_t *src);
|
||||
|
||||
utf8 *rct2_language_string_to_utf8(const char *src, int languageId);
|
||||
utf8 *rct2_language_string_to_utf8(const char *src, size_t srcSize, int languageId);
|
||||
bool language_get_localised_scenario_strings(const utf8 *scenarioFilename, rct_string_id *outStringIds);
|
||||
rct_string_id language_allocate_object_string(const utf8 * target);
|
||||
void language_free_object_string(rct_string_id stringId);
|
||||
|
||||
@@ -1213,18 +1213,17 @@ void format_string_to_upper(utf8 *dest, size_t size, rct_string_id format, void
|
||||
}
|
||||
}
|
||||
|
||||
utf8 *win1252_to_utf8_alloc(const char *src)
|
||||
utf8 *win1252_to_utf8_alloc(const char *src, size_t srcMaxSize)
|
||||
{
|
||||
size_t reservedSpace = (strlen(src) * 4) + 1;
|
||||
size_t stringLength = strnlen(src, srcMaxSize);
|
||||
size_t reservedSpace = (stringLength * 4) + 1;
|
||||
utf8 *result = malloc(reservedSpace);
|
||||
int actualSpace = win1252_to_utf8(result, src, reservedSpace);
|
||||
int actualSpace = win1252_to_utf8(result, src, stringLength, reservedSpace);
|
||||
return (utf8*)realloc(result, actualSpace);
|
||||
}
|
||||
|
||||
int win1252_to_utf8(utf8string dst, const char *src, size_t maxBufferLength)
|
||||
int win1252_to_utf8(utf8string dst, const char *src, size_t srcLength, size_t maxBufferLength)
|
||||
{
|
||||
size_t srcLength = strlen(src);
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
utf16 stackBuffer[256];
|
||||
utf16 *heapBuffer = NULL;
|
||||
|
||||
@@ -44,8 +44,8 @@ rct_string_id user_string_allocate(int base, const utf8 *text);
|
||||
void user_string_free(rct_string_id id);
|
||||
bool is_user_string_id(rct_string_id stringId);
|
||||
|
||||
utf8 *win1252_to_utf8_alloc(const char *src);
|
||||
int win1252_to_utf8(utf8string dst, const char *src, size_t maxBufferLength);
|
||||
utf8 *win1252_to_utf8_alloc(const char *src, size_t srcMaxSize);
|
||||
int win1252_to_utf8(utf8string dst, const char *src, size_t srcLength, size_t maxBufferLength);
|
||||
|
||||
int rct2_to_utf8(utf8 *dst, const char *src);
|
||||
int utf8_to_rct2(char *dst, const utf8 *src);
|
||||
|
||||
@@ -57,9 +57,8 @@ void StringTable::Read(IReadObjectContext * context, IStream * stream, uint8 id)
|
||||
entry.Id = id;
|
||||
entry.LanguageId = languageId;
|
||||
|
||||
char * stringAsWin1252 = stream->ReadString();
|
||||
utf8 * stringAsUtf8 = rct2_language_string_to_utf8(stringAsWin1252, languageId);
|
||||
Memory::Free(stringAsWin1252);
|
||||
std::string stringAsWin1252 = stream->ReadStdString();
|
||||
utf8 * stringAsUtf8 = rct2_language_string_to_utf8(stringAsWin1252.c_str(), stringAsWin1252.size(), languageId);
|
||||
|
||||
if (StringIsBlank(stringAsUtf8))
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "../core/Math.hpp"
|
||||
#include "../core/Path.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "../core/Util.hpp"
|
||||
#include "../PlatformEnvironment.h"
|
||||
#include "ScenarioRepository.h"
|
||||
#include "ScenarioSources.h"
|
||||
@@ -450,7 +451,7 @@ private:
|
||||
if (scBasic.company_value > highscore->company_value)
|
||||
{
|
||||
SafeFree(highscore->name);
|
||||
highscore->name = win1252_to_utf8_alloc(scBasic.completed_by);
|
||||
highscore->name = win1252_to_utf8_alloc(scBasic.completed_by, Util::CountOf(scBasic.completed_by));
|
||||
highscore->company_value = scBasic.company_value;
|
||||
highscore->timestamp = DATETIME64_MIN;
|
||||
break;
|
||||
@@ -461,7 +462,7 @@ private:
|
||||
{
|
||||
scenario_highscore_entry * highscore = InsertHighscore();
|
||||
highscore->fileName = String::Duplicate(scBasic.path);
|
||||
highscore->name = win1252_to_utf8_alloc(scBasic.completed_by);
|
||||
highscore->name = win1252_to_utf8_alloc(scBasic.completed_by, Util::CountOf(scBasic.completed_by));
|
||||
highscore->company_value = scBasic.company_value;
|
||||
highscore->timestamp = DATETIME64_MIN;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user