From 0c1e9603db32b4281974fdd8b8e3b505148be47e Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sat, 21 Aug 2021 20:04:04 +0200 Subject: [PATCH] HUD: Reject and warn on invalid stat types (#11548) This comes into play on older servers which do not know the "stat" type. Warnings are only logged once to avoid spam within globalstep callbacks --- src/network/clientpackethandler.cpp | 34 +++++++++++++------- src/script/common/c_content.cpp | 19 ++++++----- src/script/common/c_content.h | 10 +++--- src/script/common/c_internal.cpp | 48 ++++++++++++++++++++-------- src/script/common/c_internal.h | 6 ++-- src/script/lua_api/l_localplayer.cpp | 5 +-- src/script/lua_api/l_object.cpp | 8 +++-- 7 files changed, 86 insertions(+), 44 deletions(-) diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 50f497959..a631a3178 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -1119,17 +1119,29 @@ void Client::handleCommand_HudChange(NetworkPacket* pkt) *pkt >> server_id >> stat; - if (stat == HUD_STAT_POS || stat == HUD_STAT_SCALE || - stat == HUD_STAT_ALIGN || stat == HUD_STAT_OFFSET) - *pkt >> v2fdata; - else if (stat == HUD_STAT_NAME || stat == HUD_STAT_TEXT || stat == HUD_STAT_TEXT2) - *pkt >> sdata; - else if (stat == HUD_STAT_WORLD_POS) - *pkt >> v3fdata; - else if (stat == HUD_STAT_SIZE) - *pkt >> v2s32data; - else - *pkt >> intdata; + // Keep in sync with:server.cpp -> SendHUDChange + switch ((HudElementStat)stat) { + case HUD_STAT_POS: + case HUD_STAT_SCALE: + case HUD_STAT_ALIGN: + case HUD_STAT_OFFSET: + *pkt >> v2fdata; + break; + case HUD_STAT_NAME: + case HUD_STAT_TEXT: + case HUD_STAT_TEXT2: + *pkt >> sdata; + break; + case HUD_STAT_WORLD_POS: + *pkt >> v3fdata; + break; + case HUD_STAT_SIZE: + *pkt >> v2s32data; + break; + default: + *pkt >> intdata; + break; + } ClientEvent *event = new ClientEvent(); event->type = CE_HUDCHANGE; diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 235016be0..f13287375 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -1989,15 +1989,17 @@ void push_hud_element(lua_State *L, HudElement *elem) lua_setfield(L, -2, "style"); } -HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) +bool read_hud_change(lua_State *L, HudElementStat &stat, HudElement *elem, void **value) { - HudElementStat stat = HUD_STAT_NUMBER; - std::string statstr; - if (lua_isstring(L, 3)) { + std::string statstr = lua_tostring(L, 3); + { int statint; - statstr = lua_tostring(L, 3); - stat = string_to_enum(es_HudElementStat, statint, statstr) ? - (HudElementStat)statint : stat; + if (!string_to_enum(es_HudElementStat, statint, statstr)) { + script_log_unique(L, "Unknown HUD stat type: " + statstr, warningstream); + return false; + } + + stat = (HudElementStat)statint; } switch (stat) { @@ -2060,7 +2062,8 @@ HudElementStat read_hud_change(lua_State *L, HudElement *elem, void **value) *value = &elem->style; break; } - return stat; + + return true; } /******************************************************************************/ diff --git a/src/script/common/c_content.h b/src/script/common/c_content.h index 4dc614706..e762604a4 100644 --- a/src/script/common/c_content.h +++ b/src/script/common/c_content.h @@ -193,12 +193,12 @@ void read_json_value (lua_State *L, Json::Value &root, void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm = false, bool hitpoint = false); -void push_objectRef (lua_State *L, const u16 id); +void push_objectRef (lua_State *L, const u16 id); -void read_hud_element (lua_State *L, HudElement *elem); +void read_hud_element (lua_State *L, HudElement *elem); -void push_hud_element (lua_State *L, HudElement *elem); +void push_hud_element (lua_State *L, HudElement *elem); -HudElementStat read_hud_change (lua_State *L, HudElement *elem, void **value); +bool read_hud_change (lua_State *L, HudElementStat &stat, HudElement *elem, void **value); -void push_collision_move_result(lua_State *L, const collisionMoveResult &res); +void push_collision_move_result(lua_State *L, const collisionMoveResult &res); diff --git a/src/script/common/c_internal.cpp b/src/script/common/c_internal.cpp index ad5f836c5..66f6a9b98 100644 --- a/src/script/common/c_internal.cpp +++ b/src/script/common/c_internal.cpp @@ -18,10 +18,12 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "common/c_internal.h" +#include "util/numeric.h" #include "debug.h" #include "log.h" #include "porting.h" #include "settings.h" +#include // std::find std::string script_get_backtrace(lua_State *L) { @@ -135,24 +137,35 @@ void script_run_callbacks_f(lua_State *L, int nargs, lua_remove(L, error_handler); } -static void script_log(lua_State *L, const std::string &message, - std::ostream &log_to, bool do_error, int stack_depth) +static void script_log_add_source(lua_State *L, std::string &message, int stack_depth) { lua_Debug ar; - log_to << message << " "; if (lua_getstack(L, stack_depth, &ar)) { FATAL_ERROR_IF(!lua_getinfo(L, "Sl", &ar), "lua_getinfo() failed"); - log_to << "(at " << ar.short_src << ":" << ar.currentline << ")"; + message.append(" (at " + std::string(ar.short_src) + ":" + + std::to_string(ar.currentline) + ")"); } else { - log_to << "(at ?:?)"; + message.append(" (at ?:?)"); } - log_to << std::endl; +} - if (do_error) - script_error(L, LUA_ERRRUN, NULL, NULL); - else - infostream << script_get_backtrace(L) << std::endl; +bool script_log_unique(lua_State *L, std::string message, std::ostream &log_to, + int stack_depth) +{ + thread_local std::vector logged_messages; + + script_log_add_source(L, message, stack_depth); + u64 hash = murmur_hash_64_ua(message.data(), message.length(), 0xBADBABE); + + if (std::find(logged_messages.begin(), logged_messages.end(), hash) + == logged_messages.end()) { + + logged_messages.emplace_back(hash); + log_to << message << std::endl; + return true; + } + return false; } DeprecatedHandlingMode get_deprecated_handling_mode() @@ -174,9 +187,18 @@ DeprecatedHandlingMode get_deprecated_handling_mode() return ret; } -void log_deprecated(lua_State *L, const std::string &message, int stack_depth) +void log_deprecated(lua_State *L, std::string message, int stack_depth) { DeprecatedHandlingMode mode = get_deprecated_handling_mode(); - if (mode != DeprecatedHandlingMode::Ignore) - script_log(L, message, warningstream, mode == DeprecatedHandlingMode::Error, stack_depth); + if (mode == DeprecatedHandlingMode::Ignore) + return; + + script_log_add_source(L, message, stack_depth); + warningstream << message << std::endl; + + if (mode == DeprecatedHandlingMode::Error) + script_error(L, LUA_ERRRUN, NULL, NULL); + else + infostream << script_get_backtrace(L) << std::endl; } + diff --git a/src/script/common/c_internal.h b/src/script/common/c_internal.h index 452c2dd5e..4ddbed232 100644 --- a/src/script/common/c_internal.h +++ b/src/script/common/c_internal.h @@ -114,6 +114,9 @@ void script_error(lua_State *L, int pcall_result, const char *mod, const char *f void script_run_callbacks_f(lua_State *L, int nargs, RunCallbacksMode mode, const char *fxn); +bool script_log_unique(lua_State *L, std::string message, std::ostream &log_to, + int stack_depth = 1); + enum class DeprecatedHandlingMode { Ignore, Log, @@ -134,5 +137,4 @@ DeprecatedHandlingMode get_deprecated_handling_mode(); * @param message The deprecation method * @param stack_depth How far on the stack to the first user function (ie: not builtin or core) */ -void log_deprecated(lua_State *L, const std::string &message, - int stack_depth=1); +void log_deprecated(lua_State *L, std::string message, int stack_depth = 1); diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 59d9ea5f8..77a692f08 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -369,10 +369,11 @@ int LuaLocalPlayer::l_hud_change(lua_State *L) if (!element) return 0; + HudElementStat stat; void *unused; - read_hud_change(L, element, &unused); + bool ok = read_hud_change(L, stat, element, &unused); - lua_pushboolean(L, true); + lua_pushboolean(L, ok); return 1; } diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index c404cb63c..c915fa9e1 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1555,12 +1555,14 @@ int ObjectRef::l_hud_change(lua_State *L) if (elem == nullptr) return 0; + HudElementStat stat; void *value = nullptr; - HudElementStat stat = read_hud_change(L, elem, &value); + bool ok = read_hud_change(L, stat, elem, &value); - getServer(L)->hudChange(player, id, stat, value); + if (ok) + getServer(L)->hudChange(player, id, stat, value); - lua_pushboolean(L, true); + lua_pushboolean(L, ok); return 1; }