From 534b610a76f0eb18517dceb6efe24b47600921b2 Mon Sep 17 00:00:00 2001 From: SteelT Date: Mon, 3 Oct 2022 16:04:38 -0400 Subject: [PATCH] Plug up some holes with lib_cvRegisterVar * Error if a consvar is set to an empty string * Error if a consvar is not given a defaultvalue --- src/lua_consolelib.c | 76 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 15 deletions(-) diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index c8e914e6d..816051199 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -313,36 +313,57 @@ static int lib_cvRegisterVar(lua_State *L) #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) lua_pushnil(L); - while (lua_next(L, 1)) { + while (lua_next(L, 1)) + { // stack: cvar table, cvar userdata, key/index, value // 1 2 3 4 i = 0; k = NULL; if (lua_isnumber(L, 3)) + { i = lua_tointeger(L, 3); + } else if (lua_isstring(L, 3)) + { k = lua_tostring(L, 3); + } - if (i == 1 || (k && fasticmp(k, "name"))) { + if (i == 1 || (k && fasticmp(k, "name"))) + { if (!lua_isstring(L, 4)) + { TYPEERROR("name", LUA_TSTRING) + } cvar->name = Z_StrDup(lua_tostring(L, 4)); - } else if (i == 2 || (k && fasticmp(k, "defaultvalue"))) { + } + else if (i == 2 || (k && fasticmp(k, "defaultvalue"))) + { if (!lua_isstring(L, 4)) + { TYPEERROR("defaultvalue", LUA_TSTRING) + } cvar->defaultvalue = Z_StrDup(lua_tostring(L, 4)); - } else if (i == 3 || (k && fasticmp(k, "flags"))) { + } + else if (i == 3 || (k && fasticmp(k, "flags"))) + { if (!lua_isnumber(L, 4)) + { TYPEERROR("flags", LUA_TNUMBER) + } cvar->flags = (INT32)lua_tointeger(L, 4); - } else if (i == 4 || (k && fasticmp(k, "PossibleValue"))) { - if (lua_islightuserdata(L, 4)) { + } + else if (i == 4 || (k && fasticmp(k, "PossibleValue"))) + { + if (lua_islightuserdata(L, 4)) + { CV_PossibleValue_t *pv = lua_touserdata(L, 4); if (pv == CV_OnOff || pv == CV_YesNo || pv == CV_Unsigned || pv == CV_Natural) cvar->PossibleValue = pv; else FIELDERROR("PossibleValue", "CV_PossibleValue_t expected, got unrecognised pointer") - } else if (lua_istable(L, 4)) { + } + else if (lua_istable(L, 4)) + { // Accepts tables in the form of {MIN=0, MAX=9999} or {Red=0, Green=1, Blue=2} // and converts them to CV_PossibleValue_t {{0,"MIN"},{9999,"MAX"}} or {{0,"Red"},{1,"Green"},{2,"Blue"}} // @@ -353,7 +374,8 @@ static int lib_cvRegisterVar(lua_State *L) CV_PossibleValue_t *cvpv; lua_pushnil(L); - while (lua_next(L, 4)) { + while (lua_next(L, 4)) + { count++; lua_pop(L, 1); } @@ -367,7 +389,8 @@ static int lib_cvRegisterVar(lua_State *L) i = 0; lua_pushnil(L); - while (lua_next(L, 4)) { + while (lua_next(L, 4)) + { // stack: [...] PossibleValue table, index, value // 4 5 6 if (lua_type(L, 5) != LUA_TSTRING @@ -381,11 +404,18 @@ static int lib_cvRegisterVar(lua_State *L) cvpv[i].value = 0; cvpv[i].strvalue = NULL; cvar->PossibleValue = cvpv; - } else + } + else + { FIELDERROR("PossibleValue", va("%s or CV_PossibleValue_t expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) - } else if (cvar->flags & CV_CALL && (i == 5 || (k && fasticmp(k, "func")))) { + } + } + else if (cvar->flags & CV_CALL && (i == 5 || (k && fasticmp(k, "func")))) + { if (!lua_isfunction(L, 4)) + { TYPEERROR("func", LUA_TFUNCTION) + } lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange"); I_Assert(lua_istable(L, 5)); lua_pushlightuserdata(L, cvar); @@ -400,18 +430,34 @@ static int lib_cvRegisterVar(lua_State *L) #undef FIELDERROR #undef TYPEERROR - if (!cvar->name) - return luaL_error(L, M_GetText("Variable has no name!\n")); + if (!cvar->name || cvar->name[0] == '\0') + { + return luaL_error(L, M_GetText("Variable has no name!")); + } + + if (!cvar->defaultvalue) + { + return luaL_error(L, M_GetText("Variable has no defaultvalue!")); + } + if ((cvar->flags & CV_NOINIT) && !(cvar->flags & CV_CALL)) - return luaL_error(L, M_GetText("Variable %s has CV_NOINIT without CV_CALL\n"), cvar->name); + { + return luaL_error(L, M_GetText("Variable %s has CV_NOINIT without CV_CALL"), cvar->name); + } + if ((cvar->flags & CV_CALL) && !cvar->func) - return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function\n"), cvar->name); + { + return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function"), cvar->name); + } // actually time to register it to the console now! Finally! cvar->flags |= CV_MODIFIED; CV_RegisterVar(cvar); + if (cvar->flags & CV_MODIFIED) + { return luaL_error(L, "failed to register cvar (probable conflict with internal variable/command names)"); + } // return cvar userdata return 1;