diff --git a/src/audio/audio.c b/src/audio/audio.c index 8391881d2b..ac90544cc4 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -30,6 +30,7 @@ #include "audio.h" #include "mixer.h" #include "../openrct2.h" +#include "../util/util.h" int gAudioDeviceCount; audio_device *gAudioDevices = NULL; @@ -72,13 +73,13 @@ void audio_get_devices() gAudioDeviceCount++; gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); - strcpy(gAudioDevices[0].name, language_get_string(5510)); + safe_strncpy(gAudioDevices[0].name, language_get_string(5510), AUDIO_DEVICE_NAME_SIZE); for (i = 1; i < gAudioDeviceCount; i++) { const char *utf8_name = SDL_GetAudioDeviceName(i - 1, SDL_FALSE); if (utf8_name == NULL) utf8_name = language_get_string(5511); - strcpy(gAudioDevices[i].name, utf8_name); + safe_strncpy(gAudioDevices[i].name, utf8_name, AUDIO_DEVICE_NAME_SIZE); } } } diff --git a/src/audio/audio.h b/src/audio/audio.h index d22a26442a..7c3030903a 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -24,8 +24,10 @@ #include "../common.h" #include "../world/sprite.h" +#define AUDIO_DEVICE_NAME_SIZE 256 + typedef struct { - char name[256]; + char name[AUDIO_DEVICE_NAME_SIZE]; } audio_device; extern int gAudioDeviceCount; diff --git a/src/cmdline.c b/src/cmdline.c index bfe317abe1..586d343f48 100644 --- a/src/cmdline.c +++ b/src/cmdline.c @@ -108,7 +108,7 @@ int cmdline_run(const char **argv, int argc) if (server != NULL) { gNetworkStart = NETWORK_MODE_CLIENT; - strncpy(gNetworkStartHost, server, sizeof(gNetworkStartHost)); + safe_strncpy(gNetworkStartHost, server, sizeof(gNetworkStartHost)); } #endif // DISABLE_NETWORK @@ -152,7 +152,7 @@ static int cmdline_for_edit(const char **argv, int argc) { gOpenRCT2StartupAction = STARTUP_ACTION_EDIT; if (argc >= 1) - strcpy(gOpenRCT2StartupActionPath, argv[0]); + safe_strncpy(gOpenRCT2StartupActionPath, argv[0], 512); return 0; } @@ -163,7 +163,7 @@ static int cmdline_for_none(const char **argv, int argc) if (platform_file_exists(argv[0])) { gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; - strcpy(gOpenRCT2StartupActionPath, argv[0]); + safe_strncpy(gOpenRCT2StartupActionPath, argv[0], 512); return 0; } else { fprintf(stderr, "error: %s does not exist\n", argv[0]); diff --git a/src/cmdline_sprite.c b/src/cmdline_sprite.c index d6a6e8b2ae..d6e8ac2c21 100644 --- a/src/cmdline_sprite.c +++ b/src/cmdline_sprite.c @@ -491,7 +491,7 @@ int cmdline_for_sprite(const char **argv, int argc) int maxIndex = (int)spriteFileHeader.num_entries; int numbers = (int)floor(log(maxIndex)); - strncpy(outputPath, argv[2], MAX_PATH); + safe_strncpy(outputPath, argv[2], MAX_PATH); int pathLen = strlen(outputPath); if (pathLen >= MAX_PATH - numbers - 5){ @@ -502,7 +502,7 @@ int cmdline_for_sprite(const char **argv, int argc) for (int x = 0; x < numbers; x++){ outputPath[pathLen + x] = '0'; } - strncpy(outputPath + pathLen + numbers, ".png", MAX_PATH); + safe_strncpy(outputPath + pathLen + numbers, ".png", MAX_PATH); for (int spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++){ @@ -604,7 +604,7 @@ int cmdline_for_sprite(const char **argv, int argc) int i = 0; do { // Create image path - strcpy(imagePath, resourcePath); + safe_strncpy(imagePath, resourcePath, MAX_PATH); if (resourcePath[resourceLength - 1] == '/' || resourcePath[resourceLength - 1] == '\\') imagePath[resourceLength - 1] = 0; sprintf(imagePath, "%s%c%d.png", imagePath, platform_get_path_separator(), i); diff --git a/src/config.c b/src/config.c index 50dc70b522..a2d5d74d1a 100644 --- a/src/config.c +++ b/src/config.c @@ -758,7 +758,7 @@ static bool config_find_rct2_path(utf8 *resultPath) for (i = 0; i < countof(searchLocations); i++) { if (platform_original_game_data_exists(searchLocations[i])) { - strcpy(resultPath, searchLocations[i]); + safe_strncpy(resultPath, searchLocations[i], MAX_PATH); return true; } } @@ -774,7 +774,7 @@ bool config_find_or_browse_install_directory() if (config_find_rct2_path(path)) { SafeFree(gConfigGeneral.game_path); gConfigGeneral.game_path = malloc(strlen(path) + 1); - strcpy(gConfigGeneral.game_path, path); + safe_strncpy(gConfigGeneral.game_path, path, MAX_PATH); } else { platform_show_messagebox("Unable to find RCT2 installation directory. Please select the directory where you installed RCT2!"); installPath = platform_open_directory_browser("Please select your RCT2 directory"); @@ -1005,7 +1005,7 @@ void themes_set_default() gConfigThemes.presets = malloc(sizeof(theme_preset) * gConfigThemes.num_presets); // Set RCT2 theme - strcpy(gConfigThemes.presets[0].name, language_get_string(2741)); + safe_strncpy(gConfigThemes.presets[0].name, language_get_string(2741), THEME_PRESET_NAME_SIZE); gConfigThemes.presets[0].windows = malloc(sizeof(theme_window) * gNumThemeWindows); // Define the defaults for RCT2 here @@ -1019,7 +1019,7 @@ void themes_set_default() } // Set RCT1 theme - strcpy(gConfigThemes.presets[1].name, language_get_string(2740)); + safe_strncpy(gConfigThemes.presets[1].name, language_get_string(2740), THEME_PRESET_NAME_SIZE); gConfigThemes.presets[1].windows = malloc(sizeof(theme_window) * gNumThemeWindows); // Define the defaults for RCT1 here @@ -1113,7 +1113,7 @@ bool themes_open(const_utf8string path) if (preset == gConfigThemes.num_presets) { gConfigThemes.num_presets++; gConfigThemes.presets = realloc(gConfigThemes.presets, sizeof(theme_preset) * gConfigThemes.num_presets); - strcpy(gConfigThemes.presets[preset].name, path_get_filename(path)); + safe_strncpy(gConfigThemes.presets[preset].name, path_get_filename(path), THEME_PRESET_NAME_SIZE); path_remove_extension(gConfigThemes.presets[preset].name); gConfigThemes.presets[preset].windows = malloc(sizeof(theme_window) * gNumThemeWindows); gConfigThemes.presets[preset].features.rct1_ride_lights = false; @@ -1406,7 +1406,7 @@ static void title_sequence_open(const char *path, const char *customName) char separator = platform_get_path_separator(); // Check for the script file - strcpy(scriptPath, path); + safe_strncpy(scriptPath, path, MAX_PATH); strcat(scriptPath, "script.txt"); if (!platform_file_exists(scriptPath)) { // No script file, title sequence is invalid @@ -1427,7 +1427,7 @@ static void title_sequence_open(const char *path, const char *customName) if (customName == NULL) { char nameBuffer[MAX_PATH], *name; - strcpy(nameBuffer, path); + safe_strncpy(nameBuffer, path, MAX_PATH); name = nameBuffer + strlen(nameBuffer) - 1; while (*name == '\\' || *name == '/') { *name = 0; @@ -1436,12 +1436,12 @@ static void title_sequence_open(const char *path, const char *customName) while (*(name - 1) != '\\' && *(name - 1) != '/') { name--; } - strcpy(gConfigTitleSequences.presets[preset].name, name); + safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); gConfigTitleSequences.presets[preset].path[0] = 0; } else { - strcpy(gConfigTitleSequences.presets[preset].name, customName); - strcpy(gConfigTitleSequences.presets[preset].path, path); + safe_strncpy(gConfigTitleSequences.presets[preset].name, customName, TITLE_SEQUENCE_NAME_SIZE); + safe_strncpy(gConfigTitleSequences.presets[preset].path, path, MAX_PATH); } gConfigTitleSequences.presets[preset].saves = malloc(0); @@ -1451,23 +1451,23 @@ static void title_sequence_open(const char *path, const char *customName) } // Get the save file list - strcpy(titlePath, path); + safe_strncpy(titlePath, path, MAX_PATH); strcat(titlePath, "*.sv6"); fileEnumHandle = platform_enumerate_files_begin(titlePath); while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { gConfigTitleSequences.presets[preset].num_saves++; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); - strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); + safe_strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1][TITLE_SEQUENCE_MAX_SAVE_LENGTH - 1] = '\0'; } platform_enumerate_files_end(fileEnumHandle); - strcpy(titlePath, path); + safe_strncpy(titlePath, path, MAX_PATH); strcat(titlePath, "*.sc6"); fileEnumHandle = platform_enumerate_files_begin(titlePath); while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { gConfigTitleSequences.presets[preset].num_saves++; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); - strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); + safe_strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1][TITLE_SEQUENCE_MAX_SAVE_LENGTH - 1] = '\0'; } platform_enumerate_files_end(fileEnumHandle); diff --git a/src/config.h b/src/config.h index 8db4a4fe03..b41965c4d7 100644 --- a/src/config.h +++ b/src/config.h @@ -230,9 +230,10 @@ typedef struct { uint8 rct1_scenario_font; } theme_features; +#define THEME_PRESET_NAME_SIZE 256 typedef struct theme_preset { - char name[256]; + char name[THEME_PRESET_NAME_SIZE]; theme_window *windows; // Add structures for any other settings here @@ -260,8 +261,10 @@ typedef struct { uint8 y; // LOCATION } title_command; +#define TITLE_SEQUENCE_NAME_SIZE 256 + typedef struct { - char name[256]; + char name[TITLE_SEQUENCE_NAME_SIZE]; char path[MAX_PATH]; // Needed for non-modifiable presets char (*saves)[TITLE_SEQUENCE_MAX_SAVE_LENGTH]; title_command *commands; diff --git a/src/editor.c b/src/editor.c index b13a79ab76..8175d03ca6 100644 --- a/src/editor.c +++ b/src/editor.c @@ -90,7 +90,7 @@ void editor_load() gfx_invalidate_screen(); RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, sint16) = 0; - strcpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(2749)); + safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(2749), 0x40); } /** @@ -105,7 +105,7 @@ static int show_convert_saved_game_to_scenario_dialog(char *resultPath) char filterName[256]; format_string(title, STR_CONVERT_SAVED_GAME_TO_SCENARIO_1038, NULL); - strcpy(filename, RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char)); + safe_strncpy(filename, RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH, char), MAX_PATH); format_string(filterName, STR_RCT2_SAVED_GAME, NULL); pause_sounds(); @@ -113,7 +113,7 @@ static int show_convert_saved_game_to_scenario_dialog(char *resultPath) unpause_sounds(); if (result) - strcpy(resultPath, filename); + safe_strncpy(resultPath, filename, MAX_PATH); return result; } @@ -142,8 +142,8 @@ void editor_convert_save_to_scenario() RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_NO_MONEY_SCENARIO; RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_NO_MONEY; - strcpy(s6Info->name, (const char*)RCT2_ADDRESS_SCENARIO_NAME); - strcpy(s6Info->details, (const char*)RCT2_ADDRESS_SCENARIO_DETAILS); + safe_strncpy(s6Info->name, (const char*)RCT2_ADDRESS_SCENARIO_NAME, 64); + safe_strncpy(s6Info->details, (const char*)RCT2_ADDRESS_SCENARIO_DETAILS, 256); s6Info->objective_type = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8); s6Info->objective_arg_1 = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8); s6Info->objective_arg_2 = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_CURRENCY, sint32); diff --git a/src/game.c b/src/game.c index 42bc57e745..b16a705913 100644 --- a/src/game.c +++ b/src/game.c @@ -590,7 +590,7 @@ static int open_landscape_file_dialog() { int result; format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, STR_LOAD_LANDSCAPE_DIALOG_TITLE, 0); - strcpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_LANDSCAPES_PATH); + safe_strncpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_LANDSCAPES_PATH, MAX_PATH); format_string((char*)0x0141EE68, STR_RCT2_LANDSCAPE_FILE, 0); pause_sounds(); result = platform_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6;*.SV4;*.SC6", (char*)0x0141EE68); @@ -607,7 +607,7 @@ static int open_load_game_dialog() { int result; format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, STR_LOAD_GAME_DIALOG_TITLE, 0); - strcpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_SAVED_GAMES_PATH); + safe_strncpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_SAVED_GAMES_PATH, MAX_PATH); format_string((char*)0x0141EE68, STR_RCT2_SAVED_GAME, 0); pause_sounds(); result = platform_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6", (char*)0x0141EE68); @@ -639,7 +639,7 @@ static void load_landscape() strcpy(esi, ".SC6"); break; } - strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68); + safe_strncpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68, MAX_PATH); editor_load_landscape((char*)0x0141EF68); if (1) { @@ -874,10 +874,10 @@ int game_load_save(const char *path) { log_verbose("loading saved game, %s", path); - strcpy((char*)0x0141EF68, path); - strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, path); + safe_strncpy((char*)0x0141EF68, path, MAX_PATH); + safe_strncpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, path, MAX_PATH); - strcpy(gScenarioSaveName, path_get_filename(path)); + safe_strncpy(gScenarioSaveName, path_get_filename(path), MAX_PATH); path_remove_extension(gScenarioSaveName); SDL_RWops* rw = SDL_RWFromFile(path, "rb"); @@ -983,7 +983,7 @@ static void load_game() strcpy(esi, ".SV6"); break; } - strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68); + safe_strncpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68, MAX_PATH); if (game_load_save((char *)0x0141EF68)) { gfx_invalidate_screen(); @@ -1009,7 +1009,7 @@ static int show_save_game_dialog(char *resultPath) char filterName[256]; format_string(title, STR_SAVE_GAME_1040, NULL); - strcpy(filename, RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH_2, char)); + safe_strncpy(filename, RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH_2, char), MAX_PATH); format_string(filterName, STR_RCT2_SAVED_GAME, NULL); pause_sounds(); @@ -1017,7 +1017,7 @@ static int show_save_game_dialog(char *resultPath) unpause_sounds(); if (result) - strcpy(resultPath, filename); + safe_strncpy(resultPath, filename, MAX_PATH); return result; } @@ -1056,7 +1056,7 @@ void game_autosave() utf8 backupPath[MAX_PATH]; platform_get_user_directory(path, "save"); - strcpy(backupPath, path); + safe_strncpy(backupPath, path, MAX_PATH); strcat(path, "autosave.sv6"); strcat(backupPath, "autosave.sv6.bak"); diff --git a/src/interface/chat.c b/src/interface/chat.c index 43d66acc2d..ec783c1b4d 100644 --- a/src/interface/chat.c +++ b/src/interface/chat.c @@ -5,6 +5,7 @@ #include "../network/network.h" #include "../platform/platform.h" #include "chat.h" +#include "../util/util.h" #define CHAT_HISTORY_SIZE 10 #define CHAT_INPUT_SIZE 256 @@ -77,14 +78,14 @@ void chat_draw() if (!gChatOpen && SDL_TICKS_PASSED(SDL_GetTicks(), chat_history_get_time(i) + 10000)) { break; } - strcpy(lineBuffer, chat_history_get(i)); + safe_strncpy(lineBuffer, chat_history_get(i), CHAT_INPUT_SIZE + 10); gfx_set_dirty_blocks(x, y, x + gfx_get_string_width(lineBuffer), y + 12); gfx_draw_string(dpi, lineBuffer, 255, x, y); } if (gChatOpen) { lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); lineCh = utf8_write_codepoint(lineCh, FORMAT_CELADON); - strcpy(lineCh, _chatCurrentLine); + safe_strncpy(lineCh, _chatCurrentLine, CHAT_INPUT_SIZE); y = _chatBottom - 10; gfx_set_dirty_blocks(x, y, x + gfx_get_string_width(lineBuffer) + 7, y + 12); if (_chatCaretTicks < 15) { @@ -136,4 +137,4 @@ static uint32 chat_history_get_time(unsigned int index) static void chat_clear_input() { _chatCurrentLine[0] = 0; -} \ No newline at end of file +} diff --git a/src/interface/console.c b/src/interface/console.c index b1f3e014aa..a880cda82d 100644 --- a/src/interface/console.c +++ b/src/interface/console.c @@ -17,6 +17,7 @@ #include "../world/banner.h" #include "../world/scenery.h" #include "../management/research.h" +#include "../util/util.h" #include "console.h" #include "window.h" #include "viewport.h" @@ -187,7 +188,7 @@ void console_draw(rct_drawpixelinfo *dpi) int lineLength = min(sizeof(lineBuffer) - (size_t)utf8_get_codepoint_length(FORMAT_GREEN), (size_t)(nextLine - ch)); lineCh = lineBuffer; lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); - strncpy(lineCh, ch, lineLength); + safe_strncpy(lineCh, ch, lineLength); lineCh[lineLength] = 0; gfx_draw_string(dpi, lineBuffer, 255, x, y); diff --git a/src/interface/themes.c b/src/interface/themes.c index dd6244376d..b91f1ff6ed 100644 --- a/src/interface/themes.c +++ b/src/interface/themes.c @@ -19,6 +19,7 @@ *****************************************************************************/ #include "../localisation/string_ids.h" +#include "../util/util.h" #include "window.h" #include "themes.h" @@ -193,7 +194,7 @@ void theme_create_preset(int duplicate, const char *name) int preset = gConfigThemes.num_presets; gConfigThemes.num_presets++; gConfigThemes.presets = realloc(gConfigThemes.presets, sizeof(theme_preset) * gConfigThemes.num_presets); - strcpy(gConfigThemes.presets[preset].name, name); + safe_strncpy(gConfigThemes.presets[preset].name, name, THEME_PRESET_NAME_SIZE); gConfigThemes.presets[preset].windows = malloc(sizeof(theme_window) * gNumThemeWindows); for (int i = 0; i < (int)gNumThemeWindows; i++) { gConfigThemes.presets[preset].windows[i] = gConfigThemes.presets[duplicate].windows[i]; @@ -234,7 +235,7 @@ void theme_rename_preset(int preset, const char *newName) strcat(dest, ".ini"); platform_file_move(src, dest); - strcpy(gConfigThemes.presets[preset].name, newName); + safe_strncpy(gConfigThemes.presets[preset].name, newName, THEME_PRESET_NAME_SIZE); if (preset == gCurrentTheme) { gConfigInterface.current_theme_preset = gConfigThemes.presets[preset].name; diff --git a/src/interface/title_sequences.c b/src/interface/title_sequences.c index b008df572b..5d3b05cbb3 100644 --- a/src/interface/title_sequences.c +++ b/src/interface/title_sequences.c @@ -47,7 +47,7 @@ bool title_sequence_save_exists(int preset, const char *name) { utf8 newName[MAX_PATH]; char *extension = (char*)path_get_extension(name); - strcpy(newName, name); + safe_strncpy(newName, name, MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newName, ".sv6"); for (int i = 0; i < gConfigTitleSequences.presets[preset].num_saves; i++) { @@ -86,7 +86,7 @@ void title_sequence_create_preset(const char *name) int preset = gConfigTitleSequences.num_presets; gConfigTitleSequences.num_presets++; gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets); - strcpy(gConfigTitleSequences.presets[preset].name, name); + safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); gConfigTitleSequences.presets[preset].path[0] = 0; gConfigTitleSequences.presets[preset].saves = malloc(0); @@ -112,7 +112,7 @@ void title_sequence_duplicate_preset(int duplicate, const char *name) int preset = gConfigTitleSequences.num_presets; gConfigTitleSequences.num_presets++; gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets); - strcpy(gConfigTitleSequences.presets[preset].name, name); + safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); gConfigTitleSequences.presets[preset].path[0] = 0; size_t savesSize = sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * gConfigTitleSequences.presets[duplicate].num_saves; @@ -144,7 +144,7 @@ void title_sequence_duplicate_preset(int duplicate, const char *name) char separator = platform_get_path_separator(); for (int i = 0; i < gConfigTitleSequences.presets[preset].num_saves; i++) { if (gConfigTitleSequences.presets[duplicate].path[0]) { - strcpy(srcPath, gConfigTitleSequences.presets[duplicate].path); + safe_strncpy(srcPath, gConfigTitleSequences.presets[duplicate].path, MAX_PATH); strcat(srcPath, gConfigTitleSequences.presets[duplicate].saves[i]); } else { @@ -210,7 +210,7 @@ void title_sequence_rename_preset(int preset, const char *newName) strcat(dest, newName); platform_file_move(src, dest); - strcpy(gConfigTitleSequences.presets[preset].name, newName); + safe_strncpy(gConfigTitleSequences.presets[preset].name, newName, TITLE_SEQUENCE_NAME_SIZE); // Rename the config preset name if needed if (preset == gCurrentPreviewTitleSequence) { @@ -224,7 +224,7 @@ void title_sequence_add_save(int preset, const char *path, const char *newName) { utf8 newPath[MAX_PATH]; char *extension = (char*)path_get_extension(newName); - strcpy(newPath, newName); + safe_strncpy(newPath, newName, MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newPath, ".sv6"); if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && filename_valid_characters(newPath) && !title_sequence_save_exists(preset, newPath) && platform_file_exists(path)) { @@ -242,7 +242,7 @@ void title_sequence_add_save(int preset, const char *path, const char *newName) gConfigTitleSequences.presets[preset].num_saves++; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); - strcpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], newName); + safe_strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH); // Add the appropriate extension if needed if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], ".sv6"); @@ -272,7 +272,7 @@ void title_sequence_remove_save(int preset, int index) } for (int i = index; i < gConfigTitleSequences.presets[preset].num_saves - 1; i++) { - strcpy(gConfigTitleSequences.presets[preset].saves[i], gConfigTitleSequences.presets[preset].saves[i + 1]); + safe_strncpy(gConfigTitleSequences.presets[preset].saves[i], gConfigTitleSequences.presets[preset].saves[i + 1], TITLE_SEQUENCE_MAX_SAVE_LENGTH); } gConfigTitleSequences.presets[preset].num_saves--; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); @@ -302,7 +302,7 @@ void title_sequence_rename_save(int preset, int index, const char *newName) strcat(dest, ".sv6"); platform_file_move(src, dest); - strcpy(gConfigTitleSequences.presets[preset].saves[index], newName); + safe_strncpy(gConfigTitleSequences.presets[preset].saves[index], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH); // Add the appropriate extension if needed if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(gConfigTitleSequences.presets[preset].saves[index], ".sv6"); diff --git a/src/interface/widget.c b/src/interface/widget.c index 1ed283347b..801c5621e4 100644 --- a/src/interface/widget.c +++ b/src/interface/widget.c @@ -26,6 +26,7 @@ #include "window.h" #include "../platform/platform.h" #include "../localisation/localisation.h" +#include "../util/util.h" static void widget_frame_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex); static void widget_resize_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex); @@ -1174,7 +1175,7 @@ static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg if (!active) { if (w->widgets[widgetIndex].image != 0) { - strcpy(wrapped_string, (char*)w->widgets[widgetIndex].image); + safe_strncpy(wrapped_string, (char*)w->widgets[widgetIndex].image, 512); gfx_wrap_string(wrapped_string, r - l - 5, &no_lines, &font_height); gfx_draw_string(dpi, wrapped_string, w->colours[1], l + 2, t); } @@ -1182,7 +1183,7 @@ static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg } - strcpy(wrapped_string, gTextBoxInput); + safe_strncpy(wrapped_string, gTextBoxInput, 512); // String length needs to add 12 either side of box // +13 for cursor when max length. diff --git a/src/localisation/currency.h b/src/localisation/currency.h index c3147f7172..9ed73bf71c 100644 --- a/src/localisation/currency.h +++ b/src/localisation/currency.h @@ -44,11 +44,13 @@ typedef enum { CURRENCY_SUFFIX } CURRENCY_AFFIX; +#define CURRENCY_SYMBOL_MAX_SIZE 8 + // Currency format specification - inspired by OpenTTD typedef struct { // Rate is relative to 0.1 GBP int rate; - utf8 symbol[8]; + utf8 symbol[CURRENCY_SYMBOL_MAX_SIZE]; int affix; } rct_currency_spec; diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c index edd237f716..9e6f349513 100644 --- a/src/localisation/localisation.c +++ b/src/localisation/localisation.c @@ -364,7 +364,7 @@ void format_currency(char **dest, long long value) // Prefix if (currencySpec->affix == CURRENCY_PREFIX) { - strcpy(*dest, symbol); + safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } @@ -372,7 +372,7 @@ void format_currency(char **dest, long long value) // Currency symbol suffix if (currencySpec->affix == CURRENCY_SUFFIX) { - strcpy(*dest, symbol); + safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } } @@ -395,7 +395,7 @@ void format_currency_2dp(char **dest, long long value) // Prefix if (currencySpec->affix == CURRENCY_PREFIX) { - strcpy(*dest, symbol); + safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } @@ -408,7 +408,7 @@ void format_currency_2dp(char **dest, long long value) // Currency symbol suffix if (currencySpec->affix == CURRENCY_SUFFIX) { - strcpy(*dest, symbol); + safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } } @@ -860,7 +860,7 @@ int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength) // we need one byte for null terminator int result = strnlen(src, maxBufferLength) + 1; result = min(result, maxBufferLength); - strncpy(dst, src, maxBufferLength); + safe_strncpy(dst, src, maxBufferLength); dst[maxBufferLength - 1] = '\0'; #endif // _WIN32 diff --git a/src/localisation/user.c b/src/localisation/user.c index fea5d3eab1..e664715dd1 100644 --- a/src/localisation/user.c +++ b/src/localisation/user.c @@ -21,6 +21,7 @@ #include "../addresses.h" #include "localisation.h" #include "../ride/ride.h" +#include "../util/util.h" utf8 *gUserStrings = (char*)0x0135A8F4; @@ -54,7 +55,7 @@ rct_string_id user_string_allocate(int base, const utf8 *text) if (userString[0] != 0) continue; - strncpy(userString, text, USER_STRING_MAX_LENGTH - 1); + safe_strncpy(userString, text, USER_STRING_MAX_LENGTH - 1); return 0x8000 + (i | highBits); } RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_NAMES_DEFINED; diff --git a/src/management/news_item.c b/src/management/news_item.c index 87e17cae15..2d75402dd8 100644 --- a/src/management/news_item.c +++ b/src/management/news_item.c @@ -26,6 +26,7 @@ #include "../localisation/localisation.h" #include "../ride/ride.h" #include "../world/sprite.h" +#include "../util/util.h" #include "news_item.h" rct_news_item *gNewsItems = RCT2_ADDRESS(RCT2_ADDRESS_NEWS_ITEM_LIST, rct_news_item); @@ -324,7 +325,7 @@ void news_item_add_to_queue_raw(uint8 type, const utf8 *text, uint32 assoc) newsItem->ticks = 0; newsItem->month_year = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); newsItem->day = ((days_in_month[(newsItem->month_year & 7)] * RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16)) >> 16) + 1; - strncpy(newsItem->text, text, 255); + safe_strncpy(newsItem->text, text, 255); newsItem->text[254] = 0; // blatant disregard for what happens on the last element. diff --git a/src/network/network.cpp b/src/network/network.cpp index 82b95a8e34..a3827f86c2 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -43,6 +43,7 @@ extern "C" { #include "../localisation/localisation.h" #include "../scenario.h" #include "../windows/error.h" +#include "../util/util.h" } #pragma comment(lib, "Ws2_32.lib") @@ -147,7 +148,7 @@ void NetworkPacket::Clear() NetworkPlayer::NetworkPlayer(const char* name) { - strncpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name)); + safe_strncpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name)); NetworkPlayer::name[sizeof(NetworkPlayer::name) - 1] = 0; ping = 0; flags = 0; @@ -664,7 +665,7 @@ const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text) if (fromplayer) { lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); - strcpy(lineCh, (const char*)fromplayer->name); + safe_strncpy(lineCh, (const char*)fromplayer->name, 1024); strcat(lineCh, ": "); } strcat(formatted, text); diff --git a/src/network/twitch.cpp b/src/network/twitch.cpp index bdc1633313..06fb34b629 100644 --- a/src/network/twitch.cpp +++ b/src/network/twitch.cpp @@ -22,6 +22,7 @@ extern "C" { #include "../management/news_item.h" #include "../peep/peep.h" #include "../world/sprite.h" + #include "../util/util.h" #include "http.h" #include "twitch.h" @@ -406,14 +407,14 @@ static void twitch_parse_chat_message(const char *message) message++; ch = strchrm(message, " \t"); - strncpy(buffer, message, ch - message); + safe_strncpy(buffer, message, ch - message); buffer[ch - message] = 0; if (_strcmpi(buffer, "news") == 0) { if (gConfigTwitch.enable_news) { ch = strskipwhitespace(ch); buffer[0] = (char)FORMAT_TOPAZ; - strncpy(buffer + 1, ch, sizeof(buffer) - 2); + safe_strncpy(buffer + 1, ch, sizeof(buffer) - 2); buffer[sizeof(buffer) - 2] = 0; // Remove unsupport characters @@ -432,4 +433,4 @@ static void twitch_parse_chat_message(const char *message) } } -#endif \ No newline at end of file +#endif diff --git a/src/openrct2.c b/src/openrct2.c index 8271397a2f..8146782832 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -87,7 +87,7 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 * } // Create filter path - strcpy(filter, originalDirectory); + safe_strncpy(filter, originalDirectory, MAX_PATH); ch = strchr(filter, '*'); if (ch != NULL) *ch = 0; @@ -96,10 +96,10 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 * fileEnumHandle = platform_enumerate_files_begin(filter); while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { - strcpy(newPath, newDirectory); + safe_strncpy(newPath, newDirectory, MAX_PATH); strcat(newPath, fileInfo.path); - strcpy(oldPath, originalDirectory); + safe_strncpy(oldPath, originalDirectory, MAX_PATH); ch = strchr(oldPath, '*'); if (ch != NULL) *ch = 0; @@ -112,10 +112,10 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 * fileEnumHandle = platform_enumerate_directories_begin(originalDirectory); while (platform_enumerate_directories_next(fileEnumHandle, filter)) { - strcpy(newPath, newDirectory); + safe_strncpy(newPath, newDirectory, MAX_PATH); strcat(newPath, filter); - strcpy(oldPath, originalDirectory); + safe_strncpy(oldPath, originalDirectory, MAX_PATH); ch = strchr(oldPath, '*'); if (ch != NULL) *ch = 0; @@ -164,7 +164,7 @@ static void openrct2_set_exe_path() } int exeDelimiterIndex = (int)(exeDelimiter - exePath); - strncpy(gExePath, exePath, exeDelimiterIndex + 1); + safe_strncpy(gExePath, exePath, exeDelimiterIndex + 1); gExePath[exeDelimiterIndex] = '\0'; #endif // _WIN32 } diff --git a/src/platform/linux.c b/src/platform/linux.c index f68740a3fe..4c76595791 100644 --- a/src/platform/linux.c +++ b/src/platform/linux.c @@ -32,6 +32,7 @@ #include "../localisation/currency.h" #include "../config.h" #include "platform.h" +#include "../util/util.h" #include #include @@ -268,7 +269,7 @@ int platform_enumerate_files_begin(const utf8 *pattern) for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { - strncpy(enumFileInfo->pattern, npattern, length); + safe_strncpy(enumFileInfo->pattern, npattern, length); cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort); if (cnt < 0) { @@ -407,7 +408,7 @@ int platform_enumerate_directories_begin(const utf8 *directory) for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { - strncpy(enumFileInfo->pattern, npattern, length); + safe_strncpy(enumFileInfo->pattern, npattern, length); cnt = scandir(npattern, &enumFileInfo->fileListTemp, dirfilter, alphasort); if (cnt < 0) { @@ -475,7 +476,7 @@ bool platform_enumerate_directories_next(int handle, utf8 *path) return false; } // so very, very wrong… - strncpy(path, basename(fileName), MAX_PATH); + safe_strncpy(path, basename(fileName), MAX_PATH); strncat(path, "/", MAX_PATH); path[MAX_PATH - 1] = '\0'; return true; @@ -586,7 +587,7 @@ void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory) w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); - strcpy(outPath, path); + safe_strncpy(outPath, path, MAX_PATH); free(path); log_verbose("outPath + subDirectory = '%s'", buffer); } diff --git a/src/platform/shared.c b/src/platform/shared.c index ad6e92d93f..a04fb90b85 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -31,6 +31,7 @@ #include "../input.h" #include "../localisation/localisation.h" #include "../openrct2.h" +#include "../util/util.h" #include "platform.h" typedef void(*update_palette_func)(const uint8*, int, int); @@ -589,7 +590,7 @@ void platform_process_messages() } break; case SDL_TEXTEDITING: - strcpy(gTextInputComposition, e.edit.text); + safe_strncpy(gTextInputComposition, e.edit.text, min(e.edit.length, 32)); gTextInputCompositionStart = e.edit.start; gTextInputCompositionLength = e.edit.length; gTextInputCompositionActive = gTextInputComposition[0] != 0; diff --git a/src/platform/windows.c b/src/platform/windows.c index 5856582f0b..1b76c7df70 100644 --- a/src/platform/windows.c +++ b/src/platform/windows.c @@ -30,6 +30,7 @@ #include "../openrct2.h" #include "../localisation/language.h" #include "../localisation/currency.h" +#include "../util/util.h" #include "../config.h" #include "platform.h" @@ -386,7 +387,7 @@ void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory) if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, wOutPath))) { utf8 *outPathTemp = widechar_to_utf8(wOutPath); - strcpy(outPath, outPathTemp); + safe_strncpy(outPath, outPathTemp, MAX_PATH); free(outPathTemp); strcat(outPath, separator); diff --git a/src/scenario.c b/src/scenario.c index 292d174672..ef3db26fa1 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -77,7 +77,7 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in utf8 filename[MAX_PATH]; const char *temp_filename = path_get_filename(path); int len = strnlen(temp_filename, MAX_PATH); - strncpy(filename, temp_filename, MAX_PATH); + safe_strncpy(filename, temp_filename, MAX_PATH); if (len == MAX_PATH) { filename[MAX_PATH - 1] = '\0'; @@ -88,10 +88,10 @@ int scenario_load_basic(const char *path, rct_s6_header *header, rct_s6_info *in rct_string_id localisedStringIds[3]; if (language_get_localised_scenario_strings(filename, localisedStringIds)) { if (localisedStringIds[0] != (rct_string_id)STR_NONE) { - strncpy(info->name, language_get_string(localisedStringIds[0]), 64); + safe_strncpy(info->name, language_get_string(localisedStringIds[0]), 64); } if (localisedStringIds[2] != (rct_string_id)STR_NONE) { - strncpy(info->details, language_get_string(localisedStringIds[2]), 256); + safe_strncpy(info->details, language_get_string(localisedStringIds[2]), 256); } } else { // Checks for a scenario string object (possibly for localisation) @@ -239,7 +239,7 @@ int scenario_load_and_play_from_path(const char *path) return 0; int len = strnlen(path, MAX_PATH) + 1; - strncpy(_scenarioPath, path, len); + safe_strncpy(_scenarioPath, path, len); if (len - 1 == MAX_PATH) { _scenarioPath[MAX_PATH - 1] = '\0'; @@ -311,14 +311,14 @@ void scenario_begin() finance_update_loan_hash(); - strcpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, s6Info->details); - strcpy((char*)RCT2_ADDRESS_SCENARIO_NAME, s6Info->name); + safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, s6Info->details, 256); + safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, s6Info->name, 64); { // Get filename utf8 filename[MAX_PATH]; int len = strnlen(_scenarioFileName, MAX_PATH); - strncpy(filename, _scenarioFileName, len); + safe_strncpy(filename, _scenarioFileName, len); if (len == MAX_PATH) { filename[MAX_PATH - 1] = '\0'; @@ -329,14 +329,14 @@ void scenario_begin() rct_string_id localisedStringIds[3]; if (language_get_localised_scenario_strings(filename, localisedStringIds)) { if (localisedStringIds[0] != (rct_string_id)STR_NONE) { - strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(localisedStringIds[0]), 31); + safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(localisedStringIds[0]), 31); ((char*)RCT2_ADDRESS_SCENARIO_NAME)[31] = '\0'; } if (localisedStringIds[1] != (rct_string_id)STR_NONE) { park_set_name(language_get_string(localisedStringIds[1])); } if (localisedStringIds[2] != (rct_string_id)STR_NONE) { - strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, language_get_string(localisedStringIds[2]), 255); + safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, language_get_string(localisedStringIds[2]), 255); ((char*)RCT2_ADDRESS_SCENARIO_DETAILS)[255] = '\0'; } } else { @@ -350,12 +350,12 @@ void scenario_begin() // Set localised scenario name format_string(buffer, stex->scenario_name, 0); - strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, buffer, 31); + safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, buffer, 31); ((char*)RCT2_ADDRESS_SCENARIO_NAME)[31] = '\0'; // Set localised scenario details format_string(buffer, stex->details, 0); - strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, buffer, 255); + safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, buffer, 255); ((char*)RCT2_ADDRESS_SCENARIO_DETAILS)[255] = '\0'; } } @@ -482,8 +482,8 @@ void scenario_success_submit_name(const char *name) if (strequals(scenario->path, _scenarioFileName, 256, true)) { scenarioWinCompanyValue = RCT2_GLOBAL(0x013587C0, uint32); if (scenario->company_value == scenarioWinCompanyValue) { - strncpy(scenario->completed_by, name, 64); - strncpy((char*)0x013587D8, name, 32); + safe_strncpy(scenario->completed_by, name, 64); + safe_strncpy((char*)0x013587D8, name, 32); scenario_scores_save(); } break; @@ -786,7 +786,7 @@ int scenario_prepare_for_save() rct_stex_entry* stex = g_stexEntries[0]; if ((int)stex != 0xFFFFFFFF) { format_string(buffer, stex->scenario_name, NULL); - strncpy(s6Info->name, buffer, sizeof(s6Info->name)); + safe_strncpy(s6Info->name, buffer, sizeof(s6Info->name)); memcpy(&s6Info->entry, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0], sizeof(rct_object_entry)); } @@ -910,7 +910,7 @@ static void sub_674BCF() char *dst = &savedExpansionPackNames[i * 128]; if (RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16) & (1 << i)) { char *src = &(RCT2_ADDRESS(RCT2_ADDRESS_EXPANSION_NAMES, char)[i * 128]); - strncpy(dst, src, 128); + safe_strncpy(dst, src, 128); } else { *dst = 0; } @@ -1034,7 +1034,7 @@ int scenario_save(SDL_RWops* rw, int flags) memcpy(s6->map_elements, (void*)0x00F663B8, 0x180000); memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570); - strncpy(s6->scenario_filename, _scenarioFileName, sizeof(s6->scenario_filename)); + safe_strncpy(s6->scenario_filename, _scenarioFileName, sizeof(s6->scenario_filename)); scenario_fix_ghosts(s6); game_convert_strings_to_rct2(s6); diff --git a/src/scenario_list.c b/src/scenario_list.c index 4d38ffa338..78940c8935 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -20,6 +20,7 @@ #include "addresses.h" #include "platform/platform.h" +#include "util/util.h" #include "scenario.h" // Scenario list @@ -102,8 +103,8 @@ static void scenario_list_add(const char *path) scenario->objective_arg_1 = s6Info.objective_arg_1; scenario->objective_arg_2 = s6Info.objective_arg_2; scenario->objective_arg_3 = s6Info.objective_arg_3; - strcpy(scenario->name, s6Info.name); - strcpy(scenario->details, s6Info.details); + safe_strncpy(scenario->name, s6Info.name, 64); + safe_strncpy(scenario->details, s6Info.details, 256); } else { // Check if the scenario list buffer has room for another scenario if (gScenarioListCount >= gScenarioListCapacity) { @@ -117,7 +118,7 @@ static void scenario_list_add(const char *path) gScenarioListCount++; // Add this new scenario to the list - strcpy(scenario->path, path); + safe_strncpy(scenario->path, path, 256); scenario->flags = SCENARIO_FLAGS_VISIBLE; if (RCT2_GLOBAL(0x009AA00C, uint8) & 1) scenario->flags |= SCENARIO_FLAGS_SIXFLAGS; @@ -126,8 +127,8 @@ static void scenario_list_add(const char *path) scenario->objective_arg_1 = s6Info.objective_arg_1; scenario->objective_arg_2 = s6Info.objective_arg_2; scenario->objective_arg_3 = s6Info.objective_arg_3; - strcpy(scenario->name, s6Info.name); - strcpy(scenario->details, s6Info.details); + safe_strncpy(scenario->name, s6Info.name, 64); + safe_strncpy(scenario->details, s6Info.details, 256); } } @@ -242,4 +243,4 @@ int scenario_scores_save() SDL_RWclose(file); return 1; -} \ No newline at end of file +} diff --git a/src/title.c b/src/title.c index a7e947e94e..3852d844ed 100644 --- a/src/title.c +++ b/src/title.c @@ -349,7 +349,7 @@ static void title_do_next_script_opcode() // Construct full relative path if (gConfigTitleSequences.presets[_scriptCurrentPreset].path[0]) { - strcpy(path, gConfigTitleSequences.presets[_scriptCurrentPreset].path); + safe_strncpy(path, gConfigTitleSequences.presets[_scriptCurrentPreset].path, MAX_PATH); } else { platform_get_user_directory(path, "title sequences"); diff --git a/src/util/util.c b/src/util/util.c index 467172aed7..6138e13e39 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -181,6 +181,29 @@ int strcicmp(char const *a, char const *b) } } +char *safe_strncpy(char * destination, const char * source, size_t size) +{ + char *result = destination; + bool terminated = false; + for (size_t i = 0; i < size; i++) + { + if (*source != '\0') + { + *destination++ = *source++; + } else { + *destination = *source; + terminated = true; + break; + } + } + if (!terminated) + { + destination[size - 1] = '\0'; + log_warning("Truncating string %s to %d bytes.", destination, size); + } + return result; +} + bool utf8_is_bom(const char *str) { return str[0] == (char)0xEF && str[1] == (char)0xBB && str[2] == (char)0xBF; diff --git a/src/util/util.h b/src/util/util.h index 398ca173c4..8eba3a2b3f 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -39,6 +39,7 @@ int bitscanforward(int source); int bitcount(int source); bool strequals(const char *a, const char *b, int length, bool caseInsensitive); int strcicmp(char const *a, char const *b); +char *safe_strncpy(char * destination, const char * source, size_t num); bool utf8_is_bom(const char *str); bool str_is_null_or_empty(const char *str); diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c index 1dcbd2a15b..4416c40895 100644 --- a/src/windows/editor_bottom_toolbar.c +++ b/src/windows/editor_bottom_toolbar.c @@ -341,7 +341,7 @@ static int show_save_scenario_dialog(char *resultPath) unpause_sounds(); if (result) - strcpy(resultPath, filename); + safe_strncpy(resultPath, filename, MAX_PATH); return result; } diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index 034afb51f6..388af33f45 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -35,6 +35,7 @@ #include "../scenario.h" #include "dropdown.h" #include "error.h" +#include "../util/util.h" enum { @@ -1991,7 +1992,7 @@ static void window_editor_object_selection_textinput(rct_window *w, int widgetIn } else { memset(_filter_string, 0, sizeof(_filter_string)); - strcpy(_filter_string, text); + safe_strncpy(_filter_string, text, sizeof(_filter_string)); } filter_update_counts(); @@ -2013,8 +2014,8 @@ static bool filter_string(rct_object_entry *entry) char name_lower[MAX_PATH]; char filter_lower[sizeof(_filter_string)]; - strcpy(name_lower, name); - strcpy(filter_lower, _filter_string); + safe_strncpy(name_lower, name, MAX_PATH); + safe_strncpy(filter_lower, _filter_string, sizeof(_filter_string)); for (int i = 0; i < (int)strlen(name_lower); i++) name_lower[i] = (char)tolower(name_lower[i]); diff --git a/src/windows/editor_objective_options.c b/src/windows/editor_objective_options.c index bf7f5a26b4..9dd1d28e63 100644 --- a/src/windows/editor_objective_options.c +++ b/src/windows/editor_objective_options.c @@ -29,6 +29,7 @@ #include "dropdown.h" #include "error.h" #include "../interface/themes.h" +#include "../util/util.h" #pragma region Widgets @@ -405,11 +406,11 @@ static void window_editor_objective_options_main_mouseup(rct_window *w, int widg window_text_input_open(w, WIDX_PARK_NAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), 0, 32); break; case WIDX_SCENARIO_NAME: - strcpy((char*)0x009BC677, s6Info->name); + safe_strncpy((char*)0x009BC677, s6Info->name, 64); window_text_input_open(w, WIDX_SCENARIO_NAME, 3313, 3314, 3165, 0, 32); break; case WIDX_DETAILS: - strcpy((char*)0x009BC677, s6Info->details); + safe_strncpy((char*)0x009BC677, s6Info->details, 256); window_text_input_open(w, WIDX_DETAILS, 3315, 3316, 3165, 0, 256); break; } @@ -1002,7 +1003,7 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi if (stex != NULL) { RCT2_GLOBAL(0x013CE952 + 0, uint16) = stex->scenario_name; } else { - strcpy((char*)0x009BC677, s6Info->name); + safe_strncpy((char*)0x009BC677, s6Info->name, 64); RCT2_GLOBAL(0x013CE952 + 0, uint16) = 3165; } RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x0013573D8, uint32); @@ -1021,7 +1022,7 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi if (stex != NULL) { RCT2_GLOBAL(0x013CE952 + 0, uint16) = stex->details; } else { - strcpy((char*)0x009BC677, s6Info->details); + safe_strncpy((char*)0x009BC677, s6Info->details, 256); RCT2_GLOBAL(0x013CE952 + 0, uint16) = 3165; } RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x0013573D8, uint32); diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index a5da1ea182..cf57c1442a 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -221,7 +221,7 @@ rct_window *window_loadsave_open(int type, char *defaultName) } */ - strcpy(path, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char)); + safe_strncpy(path, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), MAX_PATH); ch = strchr(path, '*'); if (ch != NULL) *ch = 0; @@ -240,7 +240,7 @@ rct_window *window_loadsave_open(int type, char *defaultName) } */ - strcpy(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char)); + safe_strncpy(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), MAX_PATH); ch = strchr(path, '*'); if (ch != NULL) *ch = 0; @@ -273,12 +273,12 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) window_close(w); break; case WIDX_BROWSE: - strcpy(filename, _directory); + safe_strncpy(filename, _directory, MAX_PATH); if (_type & LOADSAVETYPE_SAVE) strcat(filename, (char*)RCT2_ADDRESS_SCENARIO_NAME); memset(filter, '\0', MAX_PATH); - strncpy(filter, "*", MAX_PATH); + safe_strncpy(filter, "*", MAX_PATH); strncat(filter, _extension, MAX_PATH); switch (_type) { @@ -375,7 +375,7 @@ static void window_loadsave_scrollmousedown(rct_window *w, int scrollIndex, int includeNewItem = (_type & 1) == LOADSAVETYPE_SAVE; char directory[MAX_PATH]; - strncpy(directory, _listItems[selectedItem].path, sizeof(directory)); + safe_strncpy(directory, _listItems[selectedItem].path, sizeof(directory)); window_loadsave_populate_list(includeNewItem, true, directory, _extension); window_init_scroll_widgets(w); @@ -428,7 +428,7 @@ static void window_loadsave_textinput(rct_window *w, int widgetIndex, char *text return; } - strncpy(path, _directory, sizeof(path)); + safe_strncpy(path, _directory, sizeof(path)); strncat(path, text, sizeof(path) - strnlen(path, MAX_PATH) - 1); strncat(path, _extension, sizeof(path) - strnlen(path, MAX_PATH) - 1); @@ -469,7 +469,7 @@ static void window_loadsave_paint(rct_window *w, rct_drawpixelinfo *dpi) utf8 *ch = buffer; ch = utf8_write_codepoint(ch, FORMAT_MEDIUMFONT); ch = utf8_write_codepoint(ch, FORMAT_BLACK); - strcpy(ch, _shortenedDirectory); + safe_strncpy(ch, _shortenedDirectory, sizeof(buffer) - (ch - buffer)); // Draw shadow gfx_draw_string(dpi, buffer, 0, w->x + 4, w->y + 20); @@ -599,14 +599,14 @@ static void window_loadsave_populate_list(int includeNewItem, bool browsable, co const char *src; char *dst, filter[MAX_PATH], subDir[MAX_PATH]; - strncpy(_directory, directory, sizeof(_directory)); + safe_strncpy(_directory, directory, sizeof(_directory)); if (_extension != extension) { - strncpy(_extension, extension, sizeof(_extension)); + safe_strncpy(_extension, extension, sizeof(_extension)); _extension[sizeof(_extension) - 1] = '\0'; } _shortenedDirectory[0] = '\0'; - strncpy(filter, directory, sizeof(filter)); + safe_strncpy(filter, directory, sizeof(filter)); strncat(filter, "*", sizeof(filter) - strnlen(filter, MAX_PATH) - 1); strncat(filter, extension, sizeof(filter) - strnlen(filter, MAX_PATH) - 1); @@ -638,15 +638,15 @@ static void window_loadsave_populate_list(int includeNewItem, bool browsable, co } if (!topLevel){ listItem = &_listItems[_listItemsCount]; - strncpy(listItem->name, language_get_string(2718), sizeof(listItem->name)); + safe_strncpy(listItem->name, language_get_string(2718), sizeof(listItem->name)); memset(listItem->path, '\0', MAX_PATH); - strncpy(listItem->path, directory, lastSlash + 1); + safe_strncpy(listItem->path, directory, lastSlash + 1); listItem->type = TYPE_UP; _listItemsCount++; } else if (platform_get_drives() != 0 && directory[0] != '\0'){ includeNewItem = false; listItem = &_listItems[_listItemsCount]; - strncpy(listItem->name, language_get_string(2718), sizeof(listItem->name)); + safe_strncpy(listItem->name, language_get_string(2718), sizeof(listItem->name)); memset(listItem->path, '\0', MAX_PATH); listItem->type = TYPE_UP; _listItemsCount++; @@ -655,7 +655,7 @@ static void window_loadsave_populate_list(int includeNewItem, bool browsable, co if (includeNewItem) { listItem = &_listItems[_listItemsCount]; - strncpy(listItem->name, language_get_string(2719), sizeof(listItem->name)); + safe_strncpy(listItem->name, language_get_string(2719), sizeof(listItem->name)); listItem->path[0] = '\0'; listItem->type = TYPE_NEW_FILE; _listItemsCount++; @@ -673,9 +673,9 @@ static void window_loadsave_populate_list(int includeNewItem, bool browsable, co listItem = &_listItems[_listItemsCount]; memset(listItem->path, '\0', MAX_PATH); - strncpy(listItem->path, directory, MAX_PATH); + safe_strncpy(listItem->path, directory, MAX_PATH); strncat(listItem->path, subDir, MAX_PATH); - strncpy(listItem->name, subDir, sizeof(listItem->name)); + safe_strncpy(listItem->name, subDir, sizeof(listItem->name)); listItem->type = TYPE_DIRECTORY; _listItemsCount++; } @@ -691,7 +691,7 @@ static void window_loadsave_populate_list(int includeNewItem, bool browsable, co } listItem = &_listItems[_listItemsCount]; - strncpy(listItem->path, directory, sizeof(listItem->path)); + safe_strncpy(listItem->path, directory, sizeof(listItem->path)); strncat(listItem->path, fileInfo.path, sizeof(listItem->path)); listItem->type = TYPE_FILE; listItem->date_modified = platform_file_get_modified_time(listItem->path); @@ -739,7 +739,7 @@ static void window_loadsave_select(rct_window *w, const char *path) if (gLoadSaveTitleSequenceSave) { utf8 newName[MAX_PATH]; char *extension = (char*)path_get_extension(path_get_filename(path)); - strcpy(newName, path_get_filename(path)); + safe_strncpy(newName, path_get_filename(path), MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newName, ".sv6"); if (title_sequence_save_exists(gCurrentTitleSequence, newName)) { @@ -756,7 +756,7 @@ static void window_loadsave_select(rct_window *w, const char *path) network_begin_server(gConfigNetwork.default_port); } - strcpy(gScenarioSaveName, path_get_filename(path)); + safe_strncpy(gScenarioSaveName, path_get_filename(path), MAX_PATH); path_remove_extension(gScenarioSaveName); gFirstTimeSave = 0; @@ -776,7 +776,7 @@ static void window_loadsave_select(rct_window *w, const char *path) SDL_RWclose(rw); if (success) { - strcpy(gScenarioSaveName, path_get_filename(path)); + safe_strncpy(gScenarioSaveName, path_get_filename(path), MAX_PATH); path_remove_extension(gScenarioSaveName); gFirstTimeSave = 0; @@ -921,10 +921,8 @@ static rct_window *window_overwrite_prompt_open(const char *name, const char *pa w->flags |= WF_TRANSPARENT; w->colours[0] = 154; - strncpy(_window_overwrite_prompt_name, name, sizeof(_window_overwrite_prompt_name)); - _window_overwrite_prompt_name[sizeof(_window_overwrite_prompt_name) - 1] = '\0'; - strncpy(_window_overwrite_prompt_path, path, sizeof(_window_overwrite_prompt_path)); - _window_overwrite_prompt_path[sizeof(_window_overwrite_prompt_path) - 1] = '\0'; + safe_strncpy(_window_overwrite_prompt_name, name, sizeof(_window_overwrite_prompt_name)); + safe_strncpy(_window_overwrite_prompt_path, path, sizeof(_window_overwrite_prompt_path)); return w; } diff --git a/src/windows/network_status.c b/src/windows/network_status.c index 7073aaf203..cadcbe99b9 100644 --- a/src/windows/network_status.c +++ b/src/windows/network_status.c @@ -22,6 +22,7 @@ #include "../interface/widget.h" #include "../interface/window.h" #include "../localisation/localisation.h" +#include "../util/util.h" #include "../network/network.h" enum WINDOW_NETWORK_STATUS_WIDGET_IDX { @@ -79,7 +80,7 @@ void window_network_status_open(const char* text) { rct_window* window; - strncpy(window_network_status_text, text, sizeof(window_network_status_text)); + safe_strncpy(window_network_status_text, text, sizeof(window_network_status_text)); // Check if window is already open window = window_bring_to_front_by_class(WC_NETWORK_STATUS); diff --git a/src/windows/options.c b/src/windows/options.c index 22527eb959..ed8230929c 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -43,6 +43,7 @@ #include "../title.h" #include "dropdown.h" #include "error.h" +#include "../util/util.h" enum WINDOW_OPTIONS_PAGE { WINDOW_OPTIONS_PAGE_DISPLAY, @@ -1039,8 +1040,7 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown char* devicename = gAudioDevices[dropdownIndex].name; Mixer_Init(devicename); SafeFree(gConfigSound.device); - gConfigSound.device = malloc(strlen(devicename) + 1); - strcpy(gConfigSound.device, devicename); + gConfigSound.device = strndup(devicename, AUDIO_DEVICE_NAME_SIZE); } config_save_default(); } diff --git a/src/windows/park.c b/src/windows/park.c index 94f27632cd..8f761e9f31 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -1745,7 +1745,7 @@ static void window_park_objective_paint(rct_window *w, rct_drawpixelinfo *dpi) // Scenario description x = w->x + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].top + 7; - strcpy((char*)0x009BC677, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char)); + safe_strncpy((char*)0x009BC677, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char), 256); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165; y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 222, 1191, 0); y += 5; diff --git a/src/windows/player_list.c b/src/windows/player_list.c index 8733f05780..e342dc4325 100644 --- a/src/windows/player_list.c +++ b/src/windows/player_list.c @@ -25,6 +25,7 @@ #include "../network/network.h" #include "../sprites.h" #include "../windows/dropdown.h" +#include "../util/util.h" enum WINDOW_PLAYER_LIST_WIDGET_IDX { WIDX_BACKGROUND, @@ -282,7 +283,7 @@ static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi int colour = 0; if (i == w->selected_list_item) { gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031); - strcpy(&buffer[0], network_get_player_name(i)); + safe_strncpy(&buffer[0], network_get_player_name(i), sizeof(buffer)); colour = w->colours[2]; } else { if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) { @@ -290,7 +291,7 @@ static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi } else { lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); } - strcpy(lineCh, network_get_player_name(i)); + safe_strncpy(lineCh, network_get_player_name(i), sizeof(buffer) - (lineCh - buffer)); } gfx_clip_string(buffer, 230); gfx_draw_string(dpi, buffer, colour, 0, y - 1); diff --git a/src/windows/server_list.c b/src/windows/server_list.c index 2be9576779..fb10c4442d 100644 --- a/src/windows/server_list.c +++ b/src/windows/server_list.c @@ -24,6 +24,7 @@ #include "../localisation/localisation.h" #include "../network/network.h" #include "../sprites.h" +#include "../util/util.h" #include "error.h" #define WWIDTH_MIN 500 @@ -158,7 +159,7 @@ void window_server_list_open() window_set_resize(window, WWIDTH_MIN, WHEIGHT_MIN, WWIDTH_MAX, WHEIGHT_MAX); - strncpy(_playerName, gConfigNetwork.player_name, sizeof(_playerName)); + safe_strncpy(_playerName, gConfigNetwork.player_name, sizeof(_playerName)); server_list_load_saved_servers(); window->no_list_items = _numSavedServers; @@ -277,7 +278,7 @@ static void window_server_list_textinput(rct_window *w, int widgetIndex, char *t memset(_playerName, 0, sizeof(_playerName)); } else { memset(_playerName, 0, sizeof(_playerName)); - strcpy(_playerName, text); + safe_strncpy(_playerName, text, sizeof(_playerName)); } widget_invalidate(w, WIDX_PLAYER_NAME_INPUT); diff --git a/src/windows/text_input.c b/src/windows/text_input.c index 19aff71d4b..a990d07905 100644 --- a/src/windows/text_input.c +++ b/src/windows/text_input.c @@ -125,7 +125,7 @@ void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id t // Work out the existing size of the window char wrapped_string[512]; - strcpy(wrapped_string, text_input); + safe_strncpy(wrapped_string, text_input, 512); int no_lines = 0, font_height = 0; @@ -175,7 +175,7 @@ void window_text_input_raw_open(rct_window* call_w, int call_widget, rct_string_ // Enter in the the text input buffer any existing // text. if (existing_text != NULL) - strncpy(text_input, existing_text, maxLength); + safe_strncpy(text_input, existing_text, maxLength); // In order to prevent strings that exceed the maxLength // from crashing the game. @@ -186,7 +186,7 @@ void window_text_input_raw_open(rct_window* call_w, int call_widget, rct_string_ // Work out the existing size of the window char wrapped_string[512]; - strcpy(wrapped_string, text_input); + safe_strncpy(wrapped_string, text_input, 512); int no_lines = 0, font_height = 0; @@ -273,7 +273,7 @@ static void window_text_input_paint(rct_window *w, rct_drawpixelinfo *dpi) RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16) = 0; char wrapped_string[512]; - strcpy(wrapped_string, text_input); + safe_strncpy(wrapped_string, text_input, 512); // String length needs to add 12 either side of box // +13 for cursor when max length. @@ -389,7 +389,7 @@ static void window_text_input_invalidate(rct_window *w) { // Work out the existing size of the window char wrapped_string[512]; - strcpy(wrapped_string, text_input); + safe_strncpy(wrapped_string, text_input, 512); int no_lines = 0, font_height = 0; @@ -412,4 +412,4 @@ static void window_text_input_invalidate(rct_window *w) window_text_input_widgets[WIDX_CANCEL].bottom = height - 10; window_text_input_widgets[WIDX_BACKGROUND].bottom = height - 1; -} \ No newline at end of file +} diff --git a/src/windows/title_editor.c b/src/windows/title_editor.c index e2631f5ade..8a4bd3a2e4 100644 --- a/src/windows/title_editor.c +++ b/src/windows/title_editor.c @@ -1,5 +1,5 @@ /***************************************************************************** -* Copyright (c) 2014 Maciek Baron, Dániel Tar +* Copyright (c) 2014 Maciek Baron, D�niel Tar * OpenRCT2, an open source clone of Roller Coaster Tycoon 2. * * This file is part of OpenRCT2. @@ -360,7 +360,7 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex) case WIDX_TITLE_EDITOR_LOAD: if (w->selected_list_item != -1) { if (gConfigTitleSequences.presets[gCurrentTitleSequence].path[0]) { - strcpy(path, gConfigTitleSequences.presets[gCurrentTitleSequence].path); + safe_strncpy(path, gConfigTitleSequences.presets[gCurrentTitleSequence].path, MAX_PATH); } else { platform_get_user_directory(path, "title sequences"); diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index 079f766059..58dbeb6a29 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -28,6 +28,7 @@ #include "../interface/widget.h" #include "../interface/window.h" #include "../interface/themes.h" +#include "../util/util.h" enum { WIDX_BACKGROUND, @@ -285,13 +286,13 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) // Scenario name x = w->x + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right + 4; y = w->y + window_scenarioselect_widgets[WIDX_TABCONTENT].top + 5; - strcpy((char*)0x009BC677, scenario->name); + safe_strncpy((char*)0x009BC677, scenario->name, 64); RCT2_GLOBAL(0x013CE952 + 0, short) = 3165; gfx_draw_string_centred_clipped(dpi, 1193, (void*)0x013CE952, 0, x + 85, y, 170); y += 15; // Scenario details - strcpy((char*)0x009BC677, scenario->details); + safe_strncpy((char*)0x009BC677, scenario->details, 256); RCT2_GLOBAL(0x013CE952 + 0, short) = 3165; y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, 1191, 0) + 5; @@ -304,7 +305,7 @@ static void window_scenarioselect_paint(rct_window *w, rct_drawpixelinfo *dpi) // Scenario score if (scenario->flags & SCENARIO_FLAGS_COMPLETED) { - strcpy((char*)0x009BC677, scenario->completed_by); + safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); RCT2_GLOBAL(0x013CE952 + 0, short) = 3165; RCT2_GLOBAL(0x013CE952 + 2, int) = scenario->company_value; y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 170, STR_COMPLETED_BY_WITH_COMPANY_VALUE, 0); @@ -341,7 +342,7 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * gfx_fill_rect(dpi, 0, y, w->width, y + 23, 0x02000031); // Draw scenario name - strcpy((char*)0x009BC677, scenario->name); + safe_strncpy((char*)0x009BC677, scenario->name, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165; gfx_draw_string_centred(dpi, highlighted ? highlighted_format : unhighlighted_format, 210, y + 1, 0, (void*)0x013CE952); @@ -351,7 +352,7 @@ static void window_scenarioselect_scrollpaint(rct_window *w, rct_drawpixelinfo * gfx_draw_sprite(dpi, 0x5A9F, 395, y + 1, 0); // Draw completion score - strcpy((char*)0x009BC677, scenario->completed_by); + safe_strncpy((char*)0x009BC677, scenario->completed_by, 64); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 2793; RCT2_GLOBAL(0x013CE954, short) = 3165; gfx_draw_string_centred(dpi, highlighted ? 1193 : 1191, 210, y + 11, 0, (void*)0x013CE952); diff --git a/src/windows/tooltip.c b/src/windows/tooltip.c index d8edd3dd65..724e42e331 100644 --- a/src/windows/tooltip.c +++ b/src/windows/tooltip.c @@ -225,5 +225,5 @@ static void window_tooltip_paint(rct_window *w, rct_drawpixelinfo *dpi) // Text left = w->x + ((w->width + 1) / 2) - 1; top = w->y + 1; - draw_string_centred_raw(dpi, left, top, RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TEXT_HEIGHT, uint16), gTooltip_text_buffer); -} \ No newline at end of file + draw_string_centred_raw(dpi, left, top, RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_TEXT_HEIGHT, uint16), (char *)gTooltip_text_buffer); +}