diff --git a/LuaEngine.cpp b/LuaEngine.cpp index 59ed1e8..bfd88b1 100644 --- a/LuaEngine.cpp +++ b/LuaEngine.cpp @@ -462,6 +462,47 @@ void Eluna::Push(lua_State* L, Object const* obj) } } +static int32 CheckIntegerRange(lua_State *L, int narg, int32 max, int32 min) +{ + int32 value = luaL_checklong(L, narg); + char error_buffer[64]; + + if (value > max) + { + snprintf(error_buffer, 64, "value must be less than %u", max); + return luaL_argerror(L, narg, error_buffer); + } + + if (value < min) + { + snprintf(error_buffer, 64, "value must be greater than %d", min); + return luaL_argerror(L, narg, error_buffer); + } + + return value; +} + +// This function does not work properly for anything larger than uint16. +static uint32 CheckUnsignedRange(lua_State *L, int narg, uint32 max) +{ + int32 value = luaL_checklong(L, narg); + char error_buffer[64]; + + if (value < 0) + return luaL_argerror(L, narg, "value must be greater than 0"); + + // Prevent signed-unsigned mismatch. + // This cast is safe because the value is not negative. + uint32 u_value = value; + if (u_value > max) + { + snprintf(error_buffer, 64, "value must be less than %u", max); + return luaL_argerror(L, narg, error_buffer); + } + + return u_value; +} + template<> bool Eluna::CHECKVAL(lua_State* L, int narg) { return lua_toboolean(L, narg); @@ -476,19 +517,19 @@ template<> double Eluna::CHECKVAL(lua_State* L, int narg) } template<> int8 Eluna::CHECKVAL(lua_State* L, int narg) { - return luaL_checkint(L, narg); + return CheckIntegerRange(L, narg, SCHAR_MAX, SCHAR_MIN); } template<> uint8 Eluna::CHECKVAL(lua_State* L, int narg) { - return luaL_checkunsigned(L, narg); + return CheckUnsignedRange(L, narg, UCHAR_MAX); } template<> int16 Eluna::CHECKVAL(lua_State* L, int narg) { - return luaL_checkint(L, narg); + return CheckIntegerRange(L, narg, SHRT_MIN, SHRT_MAX); } template<> uint16 Eluna::CHECKVAL(lua_State* L, int narg) { - return luaL_checkunsigned(L, narg); + return CheckUnsignedRange(L, narg, USHRT_MAX); } template<> int32 Eluna::CHECKVAL(lua_State* L, int narg) { @@ -496,7 +537,9 @@ template<> int32 Eluna::CHECKVAL(lua_State* L, int narg) } template<> uint32 Eluna::CHECKVAL(lua_State* L, int narg) { - return luaL_checkunsigned(L, narg); + // If a negative value is passed instead, it will become a large positive value. + // There is no way to catch this. + return luaL_checklong(L, narg); } template<> const char* Eluna::CHECKVAL(lua_State* L, int narg) {