diff --git a/src/base_media_func.h b/src/base_media_func.h --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -42,6 +42,11 @@ template ::FillSetDetails(IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename) { IniGroup *metadata = ini.GetGroup("metadata"); + if (metadata == nullptr) { + Debug(grf, 0, "Base " SET_TYPE "set detail loading: metadata missing."); + Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename); + return false; + } IniItem *item; fetch_metadata("name"); @@ -75,7 +80,7 @@ bool BaseSetfiles[i]; /* Find the filename first. */ - item = files->GetItem(BaseSet::file_names[i]); + item = files != nullptr ? files->GetItem(BaseSet::file_names[i]) : nullptr; if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) { Debug(grf, 0, "No " SET_TYPE " file for: {} (in {})", BaseSet::file_names[i], full_filename); return false; @@ -93,7 +98,7 @@ bool BaseSetfilename = path + filename; /* Then find the MD5 checksum */ - item = md5s->GetItem(filename); + item = md5s != nullptr ? md5s->GetItem(filename) : nullptr; if (item == nullptr || !item->value.has_value()) { Debug(grf, 0, "No MD5 checksum specified for: {} (in {})", filename, full_filename); return false; @@ -119,8 +124,8 @@ bool BaseSetGetItem(filename); - if (item == nullptr) item = origin->GetItem("default"); + item = origin != nullptr ? origin->GetItem(filename) : nullptr; + if (item == nullptr) item = origin != nullptr ? origin->GetItem("default") : nullptr; if (item == nullptr || !item->value.has_value()) { Debug(grf, 1, "No origin warning message specified for: {}", filename); file->missing_warning.clear(); diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -352,6 +352,7 @@ bool GraphicsSet::FillSetDetails(IniFile bool ret = this->BaseSet::FillSetDetails(ini, path, full_filename, false); if (ret) { IniGroup *metadata = ini.GetGroup("metadata"); + assert(metadata != nullptr); /* ret can't be true if metadata isn't present. */ IniItem *item; fetch_metadata("palette"); diff --git a/src/hotkeys.cpp b/src/hotkeys.cpp --- a/src/hotkeys.cpp +++ b/src/hotkeys.cpp @@ -277,6 +277,7 @@ HotkeyList::~HotkeyList() void HotkeyList::Load(IniFile &ini) { IniGroup *group = ini.GetGroup(this->ini_group); + if (group == nullptr) return; for (Hotkey &hotkey : this->items) { IniItem *item = group->GetItem(hotkey.name); if (item != nullptr) { diff --git a/src/ini_load.cpp b/src/ini_load.cpp --- a/src/ini_load.cpp +++ b/src/ini_load.cpp @@ -174,23 +174,17 @@ IniLoadFile::~IniLoadFile() } /** - * Get the group with the given name. If it doesn't exist - * and \a create_new is \c true create a new group. + * Get the group with the given name. * @param name name of the group to find. - * @param create_new Allow creation of group if it does not exist. - * @return The requested group if it exists or was created, else \c nullptr. + * @return The requested group or \c nullptr if not found. */ -IniGroup *IniLoadFile::GetGroup(const std::string &name, bool create_new) +IniGroup *IniLoadFile::GetGroup(const std::string &name) const { - /* does it exist already? */ for (IniGroup *group = this->group; group != nullptr; group = group->next) { if (group->name == name) return group; } - if (!create_new) return nullptr; - - /* otherwise make a new one */ - return &this->CreateGroup(name); + return nullptr; } /** diff --git a/src/ini_type.h b/src/ini_type.h --- a/src/ini_type.h +++ b/src/ini_type.h @@ -62,7 +62,7 @@ struct IniLoadFile { IniLoadFile(const char * const *list_group_names = nullptr, const char * const *seq_group_names = nullptr); virtual ~IniLoadFile(); - IniGroup *GetGroup(const std::string &name, bool create_new = true); + IniGroup *GetGroup(const std::string &name) const; IniGroup &GetOrCreateGroup(const std::string &name); IniGroup &CreateGroup(const std::string &name); void RemoveGroup(const std::string &name); diff --git a/src/music.cpp b/src/music.cpp --- a/src/music.cpp +++ b/src/music.cpp @@ -133,7 +133,7 @@ bool MusicSet::FillSetDetails(IniFile &i this->songinfo[i].filename = filename; // non-owned pointer - IniItem *item = catindex->GetItem(_music_file_names[i]); + IniItem *item = catindex != nullptr ? catindex->GetItem(_music_file_names[i]) : nullptr; if (item != nullptr && item->value.has_value() && !item->value->empty()) { /* Song has a CAT file index, assume it's MPS MIDI format */ this->songinfo[i].filetype = MTT_MPSMIDI; @@ -158,7 +158,7 @@ bool MusicSet::FillSetDetails(IniFile &i * the beginning, so we don't start reading e.g. root. */ while (*trimmed_filename == PATHSEPCHAR) trimmed_filename++; - item = names->GetItem(trimmed_filename); + item = names != nullptr ? names->GetItem(trimmed_filename) : nullptr; if (item != nullptr && item->value.has_value() && !item->value->empty()) break; } @@ -179,7 +179,7 @@ bool MusicSet::FillSetDetails(IniFile &i this->songinfo[i].tracknr = tracknr++; } - item = trimmed_filename != nullptr ? timingtrim->GetItem(trimmed_filename) : nullptr; + item = trimmed_filename != nullptr && timingtrim != nullptr ? timingtrim->GetItem(trimmed_filename) : nullptr; if (item != nullptr && item->value.has_value() && !item->value->empty()) { auto endpos = item->value->find(':'); if (endpos != std::string::npos) { diff --git a/src/settings.cpp b/src/settings.cpp --- a/src/settings.cpp +++ b/src/settings.cpp @@ -600,13 +600,15 @@ static void IniLoadSettings(IniFile &ini auto sc = s.find('.'); if (sc != std::string::npos) { group = ini.GetGroup(s.substr(0, sc)); + if (group == nullptr) group = group_def; s = s.substr(sc + 1); } else { group = group_def; } - IniItem *item = group->GetItem(s); - if (item == nullptr && group != group_def) { + IniItem *item = nullptr; + if (group != nullptr) item = group->GetItem(s); + if (item == nullptr && group != group_def && group_def != nullptr) { /* For settings.xx.yy load the settings from [settings] yy = ? in case the previous * did not exist (e.g. loading old config files with a [settings] section */ item = group_def->GetItem(s); @@ -615,7 +617,9 @@ static void IniLoadSettings(IniFile &ini /* For settings.xx.zz.yy load the settings from [zz] yy = ? in case the previous * did not exist (e.g. loading old config files with a [yapf] section */ sc = s.find('.'); - if (sc != std::string::npos) item = ini.GetGroup(s.substr(0, sc))->GetItem(s.substr(sc + 1)); + if (sc != std::string::npos) { + if (group = ini.GetGroup(s.substr(0, sc)); group != nullptr) item = group->GetItem(s.substr(sc + 1)); + } } sd->ParseValue(item, object); @@ -1087,6 +1091,7 @@ static GRFConfig *GRFLoadConfig(IniFile static IniFileVersion LoadVersionFromConfig(IniFile &ini) { IniGroup *group = ini.GetGroup("version"); + if (group == nullptr) return IFV_0; auto version_number = group->GetItem("ini_version"); /* Older ini-file versions don't have this key yet. */ @@ -1212,6 +1217,7 @@ static void RemoveEntriesFromIni(IniFile if (sc == std::string::npos) continue; IniGroup *group = ini.GetGroup(s.substr(0, sc)); + if (group == nullptr) continue; s = s.substr(sc + 1); group->RemoveItem(s); @@ -1245,7 +1251,7 @@ bool IsConversionNeeded(ConfigIniFile &i { *old_item = nullptr; - IniGroup *igroup = ini.GetGroup(group, false); + IniGroup *igroup = ini.GetGroup(group); /* If the group doesn't exist, there is nothing to convert. */ if (igroup == nullptr) return false; @@ -1295,7 +1301,7 @@ void LoadFromConfig(bool startup) /* Move no_http_content_downloads and use_relay_service from generic_ini to private_ini. */ if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) { - IniGroup *network = generic_ini.GetGroup("network", false); + IniGroup *network = generic_ini.GetGroup("network"); if (network != nullptr) { IniItem *no_http_content_downloads = network->GetItem("no_http_content_downloads"); if (no_http_content_downloads != nullptr) { @@ -1377,8 +1383,8 @@ void SaveToConfig() * just so we can add a comment before it (that is how IniFile works). * This to explain what the file is about. After doing it once, never touch * it again, as otherwise we might be reverting user changes. */ - if (IniGroup *group = private_ini.GetGroup("private", false); group != nullptr) group->comment = "; This file possibly contains private information which can identify you as person.\n"; - if (IniGroup *group = secrets_ini.GetGroup("secrets", false); group != nullptr) group->comment = "; Do not share this file with others, not even if they claim to be technical support.\n; This file contains saved passwords and other secrets that should remain private to you!\n"; + if (IniGroup *group = private_ini.GetGroup("private"); group != nullptr) group->comment = "; This file possibly contains private information which can identify you as person.\n"; + if (IniGroup *group = secrets_ini.GetGroup("secrets"); group != nullptr) group->comment = "; Do not share this file with others, not even if they claim to be technical support.\n; This file contains saved passwords and other secrets that should remain private to you!\n"; if (generic_version == IFV_0) { /* Remove some obsolete groups. These have all been loaded into other groups. */ @@ -1402,7 +1408,7 @@ void SaveToConfig() /* These variables are migrated from generic ini to private ini now. */ if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) { - IniGroup *network = generic_ini.GetGroup("network", false); + IniGroup *network = generic_ini.GetGroup("network"); if (network != nullptr) { network->RemoveItem("no_http_content_downloads"); network->RemoveItem("use_relay_service"); diff --git a/src/settingsgen/settingsgen.cpp b/src/settingsgen/settingsgen.cpp --- a/src/settingsgen/settingsgen.cpp +++ b/src/settingsgen/settingsgen.cpp @@ -195,7 +195,7 @@ static const char *DEFAULTS_GROUP_NAME */ static void DumpGroup(IniLoadFile &ifile, const char * const group_name) { - IniGroup *grp = ifile.GetGroup(group_name, false); + IniGroup *grp = ifile.GetGroup(group_name); if (grp != nullptr && grp->type == IGT_SEQUENCE) { for (IniItem *item = grp->item; item != nullptr; item = item->next) { if (!item->name.empty()) { @@ -296,9 +296,9 @@ static void DumpSections(IniLoadFile &if { static const char * const special_group_names[] = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, VALIDATION_GROUP_NAME, nullptr}; - IniGroup *default_grp = ifile.GetGroup(DEFAULTS_GROUP_NAME, false); - IniGroup *templates_grp = ifile.GetGroup(TEMPLATES_GROUP_NAME, false); - IniGroup *validation_grp = ifile.GetGroup(VALIDATION_GROUP_NAME, false); + IniGroup *default_grp = ifile.GetGroup(DEFAULTS_GROUP_NAME); + IniGroup *templates_grp = ifile.GetGroup(TEMPLATES_GROUP_NAME); + IniGroup *validation_grp = ifile.GetGroup(VALIDATION_GROUP_NAME); if (templates_grp == nullptr) return; /* Output every group, using its name as template name. */