Skip to content

Commit

Permalink
Error out on NaNs/Infinities coming from Lua.
Browse files Browse the repository at this point in the history
First, NaNs and Infs are contagious, making the game object completely unusable.
Additionally, NaNs are not filtered out by std::clamp()/std::min()/std::max() checks leading to all sorts of access violations, if the result is used to query engine array maps.

In short NaNs are evil and should never be accepted from Lua. (#1902)
  • Loading branch information
lhog authored Jan 17, 2025
1 parent f9a2f5b commit a87d53b
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 15 deletions.
12 changes: 3 additions & 9 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -403,15 +403,9 @@ if(NOT MSVC)
endif(NOT MSVC)


if(DEBUG_BUILD)
set(DEBUG_LUANAN_DEFAULT TRUE)
else()
set(DEBUG_LUANAN_DEFAULT FALSE)
endif()

option(DEBUG_LUANAN "check for nans in lua" ${DEBUG_LUANAN_DEFAULT})
if(DEBUG_LUANAN)
add_definitions(-DDEBUG_LUANAN)
option(REPORT_LUANAN "report nans/infinities in lua" TRUE)
if(REPORT_LUANAN)
add_definitions(-DREPORT_LUANAN)
endif()


Expand Down
6 changes: 4 additions & 2 deletions rts/lib/lua/include/LuaInclude.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "lib/lua/src/lstate.h"
#include "lib/streflop/streflop_cond.h"
#include "System/Log/ILog.h"
#include "System/BranchPrediction.h"



Expand Down Expand Up @@ -85,11 +86,12 @@ static inline int lua_toint(lua_State* L, int idx)
static inline float lua_tofloat(lua_State* L, int idx)
{
const float n = lua_tonumber(L, idx);
#if defined(DEBUG_LUANAN)
#if defined(REPORT_LUANAN)
// Note:
// luaL_argerror must be called from inside of lua, else it calls exit()
// so it can't be used in LuaParser::Get...() and similar
if (math::isinf(n) || math::isnan(n)) luaL_argerror(L, idx, "number expected, got NAN (check your code for div0)");
if unlikely(math::isinf(n)) luaL_argerror(L, idx, "number expected, got +-Inf (check your code for div0)");
if unlikely(math::isnan(n)) luaL_argerror(L, idx, "number expected, got +-NaN (check your code for div0)");
#endif
return n;
}
Expand Down
8 changes: 4 additions & 4 deletions rts/lib/lua/src/lauxlib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "lauxlib.h"

#include "streflop_cond.h" // SPRING
#include "System/BranchPrediction.h" // Recoil


#define FREELIST_REF 0 /* free list of references */
Expand Down Expand Up @@ -179,15 +180,14 @@ LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {
if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */
tag_error(L, narg, LUA_TNUMBER);

#if defined(DEBUG_LUANAN)
#if defined(REPORT_LUANAN)
// SPRING
// this is used by luaL_optnumber, luaL_optfloat (via luaL_optnumber),
// and luaL_checkfloat, so the asserts should cover 90% of all cases
// in which non-numbers can infect the engine -- lua_tofloat asserts
// take care of the rest
if (math::isinf(d) || math::isnan(d)) luaL_argerror(L, narg, "number expected, got NAN (check your code for div0)");
//assert(!math::isinf(d));
//assert(!math::isnan(d));
if unlikely(math::isinf(d)) luaL_argerror(L, narg, "number expected, got +-Inf (check your code for div0)");
if unlikely(math::isnan(d)) luaL_argerror(L, narg, "number expected, got +-NaN (check your code for div0)");
#endif

return d;
Expand Down

0 comments on commit a87d53b

Please sign in to comment.