-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Prevent loading of mods with invalid names #16904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 7 commits
e1efcfa
d8f08f3
9ab1852
817cd45
8c60ce8
41badce
2e240e2
61f1f06
2af97e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| // Luanti | ||
| // SPDX-License-Identifier: LGPL-2.1-or-later | ||
| // Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> | ||
|
|
||
| #include <set> | ||
| #include <map> | ||
| #include <sstream> | ||
| #include "mod_errors.h" | ||
| #include "common/c_internal.h" | ||
| #include "log.h" | ||
| #include "exceptions.h" | ||
|
|
||
| struct SingleModErrors { | ||
| std::set<std::string> messages; | ||
compmstr marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| bool was_handled; | ||
| }; | ||
|
|
||
| static std::map<std::string, SingleModErrors> mod_errors; | ||
compmstr marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| void ModErrors::logErrors() { | ||
| auto error_handling_mode = get_mod_error_handling_mode(); | ||
| if (error_handling_mode == ModErrorHandlingMode::IgnoreModError) { | ||
| return; | ||
| } | ||
|
|
||
| for (auto &pair : mod_errors) { | ||
| const auto path = pair.first; | ||
| SingleModErrors& err = pair.second; | ||
|
|
||
| if (!err.was_handled && !err.messages.empty()) { | ||
| err.was_handled = true; | ||
| std::ostringstream os; | ||
| os << "Mod at " << path << ":" << std::endl; | ||
| for (const auto& msg : err.messages) { | ||
| os << "\t" << msg << std::endl; | ||
| } | ||
| if (error_handling_mode == ModErrorHandlingMode::ThrowModError) | ||
| throw ModError(os.str()); | ||
| else | ||
| warningstream << os.str(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| void ModErrors::setModError(const std::string &path, std::string error_message) { | ||
| SingleModErrors &cur = mod_errors[path]; | ||
| auto result = cur.messages.emplace(error_message); | ||
| if (result.second) { | ||
| // New message was added, reset the was_handled flag | ||
| cur.was_handled = false; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // Luanti | ||
| // SPDX-License-Identifier: LGPL-2.1-or-later | ||
| // Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> | ||
compmstr marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| #pragma once | ||
|
|
||
| #include <string> | ||
|
|
||
| class ModErrors { | ||
| public: | ||
| static void logErrors(); | ||
| static void setModError(const std::string &path, std::string error_message); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |
| #include <fstream> | ||
| #include <json/json.h> | ||
| #include <algorithm> | ||
| #include "content/mod_errors.h" | ||
| #include "content/mods.h" | ||
| #include "database/database.h" | ||
| #include "filesys.h" | ||
|
|
@@ -16,21 +17,17 @@ | |
|
|
||
| void ModSpec::checkAndLog() const | ||
| { | ||
| if (!string_allowed(name, MODNAME_ALLOWED_CHARS)) { | ||
| throw ModError("Error loading mod \"" + name + | ||
| "\": Mod name does not follow naming conventions: " | ||
| "Only characters [a-z0-9_] are allowed."); | ||
| } | ||
| ModErrors::logErrors(); | ||
|
|
||
| // Log deprecation messages | ||
| auto handling_mode = get_deprecated_handling_mode(); | ||
| if (!deprecation_msgs.empty() && handling_mode != DeprecatedHandlingMode::Ignore) { | ||
| auto deprecation_handling_mode = get_deprecated_handling_mode(); | ||
| if (!deprecation_msgs.empty() && deprecation_handling_mode != DeprecatedHandlingMode::Ignore) { | ||
| std::ostringstream os; | ||
| os << "Mod " << name << " at " << path << ":" << std::endl; | ||
| for (auto msg : deprecation_msgs) | ||
| os << "\t" << msg << std::endl; | ||
|
|
||
| if (handling_mode == DeprecatedHandlingMode::Error) | ||
| if (deprecation_handling_mode == DeprecatedHandlingMode::Error) | ||
| throw ModError(os.str()); | ||
| else | ||
| warningstream << os.str(); | ||
|
|
@@ -70,6 +67,7 @@ bool parseModContents(ModSpec &spec) | |
| } else if (fs::IsFile(spec.path + DIR_DELIM + "modpack.txt")) { | ||
| spec.is_modpack = true; | ||
| } else if (!fs::IsFile(spec.path + DIR_DELIM + "init.lua")) { | ||
| ModErrors::setModError(spec.path, "Mod does not contain 'init.lua"); | ||
| return false; | ||
| } else { | ||
| // Is a mod | ||
|
|
@@ -86,6 +84,10 @@ bool parseModContents(ModSpec &spec) | |
| if (info.exists("name")) { | ||
| spec.name = info.get("name"); | ||
| spec.is_name_explicit = true; | ||
| if (!string_allowed(spec.name, MODNAME_ALLOWED_CHARS)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When starting Luanti in the "Start game" tab, the following warnings are logged. When I click "Configure mods", the same bunch of warnings are logged - again.
EDIT: Whereas the naming is enforced upon server start-up, there is also lack of documentation on mod names in
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll notice that nothing else prints to the log in this function. This is by design - it would be too spammy in the main menu. You should just return false here.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, should I just drop the logging altogether, or try to find somewhere to log once for mod debugging purposes?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe I could add a message to I could also set up a new
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Look at how the missing init.lua is validated because it's the same style of issue
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I got bit by the silent failure of the mod from a missing I'll take another pass at this, see if I can get these to log out inside |
||
| ModErrors::setModError(spec.path, "Mod does not follow naming conventions" "Only characters [a-zA-Z0-9_] are allowed."); | ||
| return false; | ||
| } | ||
compmstr marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } else if (!spec.is_modpack) { | ||
| spec.deprecation_msgs.push_back("Mods not having a mod.conf file with the name is deprecated."); | ||
| } | ||
|
|
@@ -192,6 +194,8 @@ std::map<std::string, ModSpec> getModsInPath( | |
| result[modname] = std::move(spec); | ||
| } | ||
| } | ||
| // Log mod errors after we finish loading them all | ||
| ModErrors::logErrors(); | ||
| return result; | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.