From 2d5bd3bf794672285cfc796edebab2f672f2cab0 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 14 Apr 2020 20:44:18 +0200 Subject: scriptapi: Some small optimizations to value pushing (#9669) --- src/script/common/c_converter.cpp | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'src/script/common/c_converter.cpp') diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index 3c2f75641..334af61c3 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -62,7 +62,7 @@ void push_float_string(lua_State *L, float value) void push_v3f(lua_State *L, v3f p) { - lua_newtable(L); + lua_createtable(L, 0, 3); lua_pushnumber(L, p.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, p.Y); @@ -73,7 +73,7 @@ void push_v3f(lua_State *L, v3f p) void push_v2f(lua_State *L, v2f p) { - lua_newtable(L); + lua_createtable(L, 0, 2); lua_pushnumber(L, p.X); lua_setfield(L, -2, "x"); lua_pushnumber(L, p.Y); @@ -82,7 +82,7 @@ void push_v2f(lua_State *L, v2f p) void push_v3_float_string(lua_State *L, v3f p) { - lua_newtable(L); + lua_createtable(L, 0, 3); push_float_string(L, p.X); lua_setfield(L, -2, "x"); push_float_string(L, p.Y); @@ -93,7 +93,7 @@ void push_v3_float_string(lua_State *L, v3f p) void push_v2_float_string(lua_State *L, v2f p) { - lua_newtable(L); + lua_createtable(L, 0, 2); push_float_string(L, p.X); lua_setfield(L, -2, "x"); push_float_string(L, p.Y); @@ -115,19 +115,19 @@ v2s16 read_v2s16(lua_State *L, int index) void push_v2s16(lua_State *L, v2s16 p) { - lua_newtable(L); - lua_pushnumber(L, p.X); + lua_createtable(L, 0, 2); + lua_pushinteger(L, p.X); lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); + lua_pushinteger(L, p.Y); lua_setfield(L, -2, "y"); } void push_v2s32(lua_State *L, v2s32 p) { - lua_newtable(L); - lua_pushnumber(L, p.X); + lua_createtable(L, 0, 2); + lua_pushinteger(L, p.X); lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); + lua_pushinteger(L, p.Y); lua_setfield(L, -2, "y"); } @@ -250,14 +250,14 @@ v3d check_v3d(lua_State *L, int index) void push_ARGB8(lua_State *L, video::SColor color) { - lua_newtable(L); - lua_pushnumber(L, color.getAlpha()); + lua_createtable(L, 0, 4); + lua_pushinteger(L, color.getAlpha()); lua_setfield(L, -2, "a"); - lua_pushnumber(L, color.getRed()); + lua_pushinteger(L, color.getRed()); lua_setfield(L, -2, "r"); - lua_pushnumber(L, color.getGreen()); + lua_pushinteger(L, color.getGreen()); lua_setfield(L, -2, "g"); - lua_pushnumber(L, color.getBlue()); + lua_pushinteger(L, color.getBlue()); lua_setfield(L, -2, "b"); } @@ -274,12 +274,12 @@ v3f checkFloatPos(lua_State *L, int index) void push_v3s16(lua_State *L, v3s16 p) { - lua_newtable(L); - lua_pushnumber(L, p.X); + lua_createtable(L, 0, 3); + lua_pushinteger(L, p.X); lua_setfield(L, -2, "x"); - lua_pushnumber(L, p.Y); + lua_pushinteger(L, p.Y); lua_setfield(L, -2, "y"); - lua_pushnumber(L, p.Z); + lua_pushinteger(L, p.Z); lua_setfield(L, -2, "z"); } @@ -386,7 +386,7 @@ aabb3f read_aabb3f(lua_State *L, int index, f32 scale) void push_aabb3f(lua_State *L, aabb3f box) { - lua_newtable(L); + lua_createtable(L, 6, 0); lua_pushnumber(L, box.MinEdge.X); lua_rawseti(L, -2, 1); lua_pushnumber(L, box.MinEdge.Y); -- cgit v1.2.3 From be71e70a91a3c857652a8b037dac7adf9d0fcdd1 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 27 Apr 2020 07:02:39 +0200 Subject: Script: Enforce type checks if not nil (#9748) * Script: Enforce type checks if not nil --- src/script/common/c_content.cpp | 76 ++++++++++++++++++++++---------------- src/script/common/c_converter.cpp | 32 ++++++++-------- src/script/common/c_converter.h | 6 +-- src/script/lua_api/l_inventory.cpp | 14 ++++--- 4 files changed, 72 insertions(+), 56 deletions(-) (limited to 'src/script/common/c_converter.cpp') diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 25dada757..8335fccb5 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -102,7 +102,8 @@ void read_item_definition(lua_State* L, int index, lua_pop(L, 1); lua_getfield(L, index, "sounds"); - if(lua_istable(L, -1)){ + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TTABLE); lua_getfield(L, -1, "place"); read_soundspec(L, -1, def.sound_place); lua_pop(L, 1); @@ -182,9 +183,11 @@ void read_object_properties(lua_State *L, int index, { if(index < 0) index = lua_gettop(L) + 1 + index; - if(!lua_istable(L, index)) + if (lua_isnil(L, index)) return; + luaL_checktype(L, -1, LUA_TTABLE); + int hp_max = 0; if (getintfield(L, -1, "hp_max", hp_max)) { prop->hp_max = (u16)rangelim(hp_max, 0, U16_MAX); @@ -1027,13 +1030,15 @@ void read_soundspec(lua_State *L, int index, SimpleSoundSpec &spec) { if(index < 0) index = lua_gettop(L) + 1 + index; - if(lua_isnil(L, index)){ - } else if(lua_istable(L, index)){ + if (lua_isnil(L, index)) + return; + + if (lua_istable(L, index)) { getstringfield(L, index, "name", spec.name); getfloatfield(L, index, "gain", spec.gain); getfloatfield(L, index, "fade", spec.fade); getfloatfield(L, index, "pitch", spec.pitch); - } else if(lua_isstring(L, index)){ + } else if (lua_isstring(L, index)) { spec.name = lua_tostring(L, index); } } @@ -1055,9 +1060,13 @@ void push_soundspec(lua_State *L, const SimpleSoundSpec &spec) NodeBox read_nodebox(lua_State *L, int index) { NodeBox nodebox; - if(lua_istable(L, -1)){ - nodebox.type = (NodeBoxType)getenumfield(L, index, "type", - ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR); + if (lua_isnil(L, -1)) + return nodebox; + + luaL_checktype(L, -1, LUA_TTABLE); + + nodebox.type = (NodeBoxType)getenumfield(L, index, "type", + ScriptApiNode::es_NodeBoxType, NODEBOX_REGULAR); #define NODEBOXREAD(n, s){ \ lua_getfield(L, index, (s)); \ @@ -1067,30 +1076,30 @@ NodeBox read_nodebox(lua_State *L, int index) } #define NODEBOXREADVEC(n, s) \ - lua_getfield(L, index, (s)); \ - if (lua_istable(L, -1)) \ - (n) = read_aabb3f_vector(L, -1, BS); \ - lua_pop(L, 1); + lua_getfield(L, index, (s)); \ + if (lua_istable(L, -1)) \ + (n) = read_aabb3f_vector(L, -1, BS); \ + lua_pop(L, 1); + + NODEBOXREADVEC(nodebox.fixed, "fixed"); + NODEBOXREAD(nodebox.wall_top, "wall_top"); + NODEBOXREAD(nodebox.wall_bottom, "wall_bottom"); + NODEBOXREAD(nodebox.wall_side, "wall_side"); + NODEBOXREADVEC(nodebox.connect_top, "connect_top"); + NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom"); + NODEBOXREADVEC(nodebox.connect_front, "connect_front"); + NODEBOXREADVEC(nodebox.connect_left, "connect_left"); + NODEBOXREADVEC(nodebox.connect_back, "connect_back"); + NODEBOXREADVEC(nodebox.connect_right, "connect_right"); + NODEBOXREADVEC(nodebox.disconnected_top, "disconnected_top"); + NODEBOXREADVEC(nodebox.disconnected_bottom, "disconnected_bottom"); + NODEBOXREADVEC(nodebox.disconnected_front, "disconnected_front"); + NODEBOXREADVEC(nodebox.disconnected_left, "disconnected_left"); + NODEBOXREADVEC(nodebox.disconnected_back, "disconnected_back"); + NODEBOXREADVEC(nodebox.disconnected_right, "disconnected_right"); + NODEBOXREADVEC(nodebox.disconnected, "disconnected"); + NODEBOXREADVEC(nodebox.disconnected_sides, "disconnected_sides"); - NODEBOXREADVEC(nodebox.fixed, "fixed"); - NODEBOXREAD(nodebox.wall_top, "wall_top"); - NODEBOXREAD(nodebox.wall_bottom, "wall_bottom"); - NODEBOXREAD(nodebox.wall_side, "wall_side"); - NODEBOXREADVEC(nodebox.connect_top, "connect_top"); - NODEBOXREADVEC(nodebox.connect_bottom, "connect_bottom"); - NODEBOXREADVEC(nodebox.connect_front, "connect_front"); - NODEBOXREADVEC(nodebox.connect_left, "connect_left"); - NODEBOXREADVEC(nodebox.connect_back, "connect_back"); - NODEBOXREADVEC(nodebox.connect_right, "connect_right"); - NODEBOXREADVEC(nodebox.disconnected_top, "disconnected_top"); - NODEBOXREADVEC(nodebox.disconnected_bottom, "disconnected_bottom"); - NODEBOXREADVEC(nodebox.disconnected_front, "disconnected_front"); - NODEBOXREADVEC(nodebox.disconnected_left, "disconnected_left"); - NODEBOXREADVEC(nodebox.disconnected_back, "disconnected_back"); - NODEBOXREADVEC(nodebox.disconnected_right, "disconnected_right"); - NODEBOXREADVEC(nodebox.disconnected, "disconnected"); - NODEBOXREADVEC(nodebox.disconnected_sides, "disconnected_sides"); - } return nodebox; } @@ -1519,8 +1528,11 @@ void push_flags_string(lua_State *L, FlagDesc *flagdesc, u32 flags, u32 flagmask /******************************************************************************/ void read_groups(lua_State *L, int index, ItemGroupList &result) { - if (!lua_istable(L,index)) + if (lua_isnil(L, index)) return; + + luaL_checktype(L, index, LUA_TTABLE); + result.clear(); lua_pushnil(L); if (index < 0) diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index 334af61c3..279d8b1a5 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -33,10 +33,9 @@ extern "C" { #define CHECK_TYPE(index, name, type) { \ int t = lua_type(L, (index)); \ if (t != (type)) { \ - std::string traceback = script_get_backtrace(L); \ throw LuaError(std::string("Invalid ") + (name) + \ " (expected " + lua_typename(L, (type)) + \ - " got " + lua_typename(L, t) + ").\n" + traceback); \ + " got " + lua_typename(L, t) + ")."); \ } \ } #define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER) @@ -457,12 +456,22 @@ size_t read_stringlist(lua_State *L, int index, std::vector *result Table field getters */ +bool check_field_or_nil(lua_State *L, int index, int type, const char *fieldname) +{ + if (lua_isnil(L, index)) + return false; + + CHECK_TYPE(index, std::string("field \"") + fieldname + '"', type); + return true; +} + bool getstringfield(lua_State *L, int table, const char *fieldname, std::string &result) { lua_getfield(L, table, fieldname); bool got = false; - if(lua_isstring(L, -1)){ + + if (check_field_or_nil(L, -1, LUA_TSTRING, fieldname)) { size_t len = 0; const char *ptr = lua_tolstring(L, -1, &len); if (ptr) { @@ -479,7 +488,8 @@ bool getfloatfield(lua_State *L, int table, { lua_getfield(L, table, fieldname); bool got = false; - if(lua_isnumber(L, -1)){ + + if (check_field_or_nil(L, -1, LUA_TNUMBER, fieldname)) { result = lua_tonumber(L, -1); got = true; } @@ -492,7 +502,8 @@ bool getboolfield(lua_State *L, int table, { lua_getfield(L, table, fieldname); bool got = false; - if(lua_isboolean(L, -1)){ + + if (check_field_or_nil(L, -1, LUA_TBOOLEAN, fieldname)){ result = lua_toboolean(L, -1); got = true; } @@ -511,17 +522,6 @@ size_t getstringlistfield(lua_State *L, int table, const char *fieldname, return num_strings_read; } -std::string checkstringfield(lua_State *L, int table, - const char *fieldname) -{ - lua_getfield(L, table, fieldname); - CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING); - size_t len; - const char *s = lua_tolstring(L, -1, &len); - lua_pop(L, 1); - return std::string(s, len); -} - std::string getstringfield_default(lua_State *L, int table, const char *fieldname, const std::string &default_) { diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h index 9620bf75a..a4a7079fd 100644 --- a/src/script/common/c_converter.h +++ b/src/script/common/c_converter.h @@ -45,13 +45,15 @@ float getfloatfield_default(lua_State *L, int table, int getintfield_default(lua_State *L, int table, const char *fieldname, int default_); +bool check_field_or_nil(lua_State *L, int index, int type, const char *fieldname); + template bool getintfield(lua_State *L, int table, const char *fieldname, T &result) { lua_getfield(L, table, fieldname); bool got = false; - if (lua_isnumber(L, -1)){ + if (check_field_or_nil(L, -1, LUA_TNUMBER, fieldname)){ result = lua_tointeger(L, -1); got = true; } @@ -87,8 +89,6 @@ bool getboolfield(lua_State *L, int table, const char *fieldname, bool &result); bool getfloatfield(lua_State *L, int table, const char *fieldname, float &result); -std::string checkstringfield(lua_State *L, int table, - const char *fieldname); void setstringfield(lua_State *L, int table, const char *fieldname, const std::string &value); diff --git a/src/script/lua_api/l_inventory.cpp b/src/script/lua_api/l_inventory.cpp index 6e7afa4a4..4c8977898 100644 --- a/src/script/lua_api/l_inventory.cpp +++ b/src/script/lua_api/l_inventory.cpp @@ -487,7 +487,9 @@ int ModApiInventory::l_get_inventory(lua_State *L) { InventoryLocation loc; - std::string type = checkstringfield(L, 1, "type"); + lua_getfield(L, 1, "type"); + std::string type = luaL_checkstring(L, -1); + lua_pop(L, 1); if(type == "node"){ MAP_LOCK_REQUIRED; @@ -504,11 +506,13 @@ int ModApiInventory::l_get_inventory(lua_State *L) NO_MAP_LOCK_REQUIRED; if (type == "player") { - std::string name = checkstringfield(L, 1, "name"); - loc.setPlayer(name); + lua_getfield(L, 1, "name"); + loc.setPlayer(luaL_checkstring(L, -1)); + lua_pop(L, 1); } else if (type == "detached") { - std::string name = checkstringfield(L, 1, "name"); - loc.setDetached(name); + lua_getfield(L, 1, "name"); + loc.setDetached(luaL_checkstring(L, -1)); + lua_pop(L, 1); } if (getServer(L)->getInventory(loc) != NULL) -- cgit v1.2.3 From 42a9b45c21ad407689950e3a4c90cb3894142260 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Mon, 1 Jun 2020 19:02:15 +0200 Subject: Lua API: Log incorrect parameter types as error (#9954) Incorrect parameter types are logged as errors, taking coercion into account. This is a workaround to ensure mod compatibility. Duplicate warnings are ignored per server instance. --- src/script/common/c_converter.cpp | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) (limited to 'src/script/common/c_converter.cpp') diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index 279d8b1a5..de0cdfbf4 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -28,6 +28,7 @@ extern "C" { #include "common/c_converter.h" #include "common/c_internal.h" #include "constants.h" +#include #define CHECK_TYPE(index, name, type) { \ @@ -458,11 +459,36 @@ size_t read_stringlist(lua_State *L, int index, std::vector *result bool check_field_or_nil(lua_State *L, int index, int type, const char *fieldname) { - if (lua_isnil(L, index)) + static thread_local std::set warned_msgs; + + int t = lua_type(L, index); + if (t == LUA_TNIL) return false; - CHECK_TYPE(index, std::string("field \"") + fieldname + '"', type); - return true; + if (t == type) + return true; + + // Check coercion types + if (type == LUA_TNUMBER) { + if (lua_isnumber(L, index)) + return true; + } else if (type == LUA_TSTRING) { + if (lua_isstring(L, index)) + return true; + } + + // Types mismatch. Log unique line. + std::string backtrace = std::string("Invalid field ") + fieldname + + " (expected " + lua_typename(L, type) + + " got " + lua_typename(L, t) + ").\n" + script_get_backtrace(L); + + u64 hash = murmur_hash_64_ua(backtrace.data(), backtrace.length(), 0xBADBABE); + if (warned_msgs.find(hash) == warned_msgs.end()) { + errorstream << backtrace << std::endl; + warned_msgs.insert(hash); + } + + return false; } bool getstringfield(lua_State *L, int table, -- cgit v1.2.3 From 70df3d54f37c280f7afe60f6e964b8406577f39f Mon Sep 17 00:00:00 2001 From: sfan5 Date: Thu, 9 Jul 2020 22:01:46 +0200 Subject: Quick workaround for crashing destructor on Mingw32 closes #10137 --- src/script/common/c_converter.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/script/common/c_converter.cpp') diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index de0cdfbf4..eb6ab5331 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -457,9 +457,17 @@ size_t read_stringlist(lua_State *L, int index, std::vector *result Table field getters */ +#if defined(__MINGW32__) && !defined(__MINGW64__) +/* MinGW 32-bit somehow crashes in the std::set destructor when this + * variable is thread-local, so just don't do that. */ +static std::set warned_msgs; +#endif + bool check_field_or_nil(lua_State *L, int index, int type, const char *fieldname) { - static thread_local std::set warned_msgs; +#if !defined(__MINGW32__) || defined(__MINGW64__) + thread_local std::set warned_msgs; +#endif int t = lua_type(L, index); if (t == LUA_TNIL) -- cgit v1.2.3