Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d07baa3

Browse files
Pirulaxpatrikjuvonen
andauthored
Detect integral underflow, NaN and inf values in the new parser (#2114)
* Detect integral under/overflow and NaN * Use PopUnsafe instead of PopPrimitive for T = CVector, CMatrix, SColor * Refactor code --------- Co-authored-by: patrikjuvonen <22572159+patrikjuvonen@users.noreply.github.com>
1 parent 92eb887 commit d07baa3

File tree

2 files changed

+53
-96
lines changed

2 files changed

+53
-96
lines changed

‎Shared/mods/deathmatch/logic/lua/CLuaFunctionParser.h‎

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -352,19 +352,41 @@ struct CLuaFunctionParserBase
352352
if constexpr (std::is_same_v<T, dummy_type>)
353353
return dummy_type{};
354354
// primitive types are directly popped
355-
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view> || std::is_integral_v<T>)
355+
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view>)
356356
return lua::PopPrimitive<T>(L, index);
357-
// floats/doubles may not be NaN
358-
else if constexpr (std::is_same_v<T, float> || std::is_same_v<T, double>)
357+
else if constexpr (std::is_same_v<T, bool>)
358+
return lua::PopPrimitive<T>(L, index);
359+
else if constexpr (std::is_integral_v<T> || std::is_floating_point_v<T>) // bool is an integral type, so must pop it before ^^
359360
{
360-
T value = lua::PopPrimitive<T>(L, index);
361-
if (std::isnan(value))
362-
{
361+
constauto number = lua::PopPrimitive<lua_Number>(L, index);
362+
363+
constauto SetError = [&](constchar* expected, constchar* got) {
363364
// Subtract one from the index, as the call to lua::PopPrimitive above increments the index, even if the
364365
// underlying element is of a wrong type
365-
SetBadArgumentError(L, "number", index - 1, "NaN");
366+
SetBadArgumentError(L, expected, index - 1, got);
367+
};
368+
369+
if (std::isnan(number))
370+
{
371+
SetError("number", "NaN");
372+
return static_cast<T>(number);
373+
}
374+
375+
if (std::isinf(number)) {
376+
SetError("number", "inf");
377+
return static_cast<T>(number);
366378
}
367-
return value;
379+
380+
// NOTE/TODO: Use C++20 `std::in_range` here instead
381+
// For now this doesn't do all the safety checks, but this should be "good enough" [until we switch to C++20]
382+
if constexpr (std::is_integral_v<T> && std::is_unsigned_v<T>)
383+
{
384+
SetError("positive number", "negative");
385+
386+
return static_cast<T>(static_cast<int64_t>(number));
387+
}
388+
389+
return static_cast<T>(number);
368390
}
369391
else if constexpr (std::is_enum_v<T>)
370392
{
@@ -488,10 +510,7 @@ struct CLuaFunctionParserBase
488510
{
489511
if (lua_isnumber(L, index))
490512
{
491-
CVector2D vec;
492-
vec.fX = lua::PopPrimitive<float>(L, index);
493-
vec.fY = lua::PopPrimitive<float>(L, index);
494-
return vec;
513+
return { PopUnsafe<float>(L, index), PopUnsafe<float>(L, index) };
495514
}
496515
else
497516
{
@@ -520,11 +539,7 @@ struct CLuaFunctionParserBase
520539
{
521540
if (lua_isnumber(L, index))
522541
{
523-
CVector vec;
524-
vec.fX = lua::PopPrimitive<float>(L, index);
525-
vec.fY = lua::PopPrimitive<float>(L, index);
526-
vec.fZ = lua::PopPrimitive<float>(L, index);
527-
return vec;
542+
return { PopUnsafe<float>(L, index), PopUnsafe<float>(L, index), PopUnsafe<float>(L, index) };
528543
}
529544
else
530545
{
@@ -551,12 +566,8 @@ struct CLuaFunctionParserBase
551566
{
552567
if (lua_isnumber(L, index))
553568
{
554-
CVector4D vec;
555-
vec.fX = lua::PopPrimitive<float>(L, index);
556-
vec.fY = lua::PopPrimitive<float>(L, index);
557-
vec.fZ = lua::PopPrimitive<float>(L, index);
558-
vec.fW = lua::PopPrimitive<float>(L, index);
559-
return vec;
569+
return { PopUnsafe<float>(L, index), PopUnsafe<float>(L, index),
570+
PopUnsafe<float>(L, index), PopUnsafe<float>(L, index) };
560571
}
561572
else
562573
{
@@ -583,19 +594,17 @@ struct CLuaFunctionParserBase
583594
{
584595
if (lua_isnumber(L, index))
585596
{
597+
const auto ReadVector = [&] {
598+
return CVector(PopUnsafe<float>(L, index), PopUnsafe<float>(L, index), PopUnsafe<float>(L, index));
599+
};
600+
586601
CMatrix matrix;
587-
matrix.vRight.fX = lua::PopPrimitive<float>(L, index);
588-
matrix.vRight.fY = lua::PopPrimitive<float>(L, index);
589-
matrix.vRight.fZ = lua::PopPrimitive<float>(L, index);
590-
matrix.vFront.fX = lua::PopPrimitive<float>(L, index);
591-
matrix.vFront.fY = lua::PopPrimitive<float>(L, index);
592-
matrix.vFront.fZ = lua::PopPrimitive<float>(L, index);
593-
matrix.vUp.fX = lua::PopPrimitive<float>(L, index);
594-
matrix.vUp.fY = lua::PopPrimitive<float>(L, index);
595-
matrix.vUp.fZ = lua::PopPrimitive<float>(L, index);
596-
matrix.vPos.fX = lua::PopPrimitive<float>(L, index);
597-
matrix.vPos.fY = lua::PopPrimitive<float>(L, index);
598-
matrix.vPos.fZ = lua::PopPrimitive<float>(L, index);
602+
603+
matrix.vRight = ReadVector();
604+
matrix.vFront = ReadVector();
605+
matrix.vUp = ReadVector();
606+
matrix.vPos = ReadVector();
607+
599608
return matrix;
600609
}
601610
else
@@ -635,7 +644,7 @@ struct CLuaFunctionParserBase
635644
return static_cast<T>(result);
636645
}
637646
else if constexpr (std::is_same_v<T, SColor>)
638-
return static_cast<unsigned long>(lua::PopPrimitive<int64_t>(L, index));
647+
return static_cast<unsigned long>(static_cast<int64_t>(lua::PopPrimitive<lua_Number>(L, index)));
639648
else if constexpr (std::is_same_v<T, CLuaArgument>)
640649
{
641650
CLuaArgument argument;

‎Shared/mods/deathmatch/logic/lua/LuaBasic.cpp‎

Lines changed: 8 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -29,66 +29,6 @@ namespace lua
2929
return outValue;
3030
}
3131

32-
template <>
33-
int PopPrimitive<int>(lua_State* L, int& index)
34-
{
35-
return static_cast<int>(lua_tonumber(L, index++));
36-
}
37-
38-
template <>
39-
unsigned int PopPrimitive<unsigned int>(lua_State* L, int& index)
40-
{
41-
return static_cast<unsigned int>(lua_tonumber(L, index++));
42-
}
43-
44-
template <>
45-
short PopPrimitive<short>(lua_State* L, int& index)
46-
{
47-
return static_cast<short>(lua_tonumber(L, index++));
48-
}
49-
50-
template <>
51-
unsigned short PopPrimitive<unsigned short>(lua_State* L, int& index)
52-
{
53-
return static_cast<unsigned short>(lua_tonumber(L, index++));
54-
}
55-
56-
template <>
57-
char PopPrimitive<char>(lua_State* L, int& index)
58-
{
59-
return static_cast<char>(lua_tonumber(L, index++));
60-
}
61-
62-
template <>
63-
unsigned char PopPrimitive<unsigned char>(lua_State* L, int& index)
64-
{
65-
return static_cast<unsigned char>(lua_tonumber(L, index++));
66-
}
67-
68-
template <>
69-
int64_t PopPrimitive<int64_t>(lua_State* L, int& index)
70-
{
71-
return static_cast<int64_t>(lua_tonumber(L, index++));
72-
}
73-
74-
template <>
75-
uint64_t PopPrimitive<uint64_t>(lua_State* L, int& index)
76-
{
77-
return static_cast<uint64_t>(lua_tonumber(L, index++));
78-
}
79-
80-
template <>
81-
float PopPrimitive<float>(lua_State* L, int& index)
82-
{
83-
return static_cast<float>(lua_tonumber(L, index++));
84-
}
85-
86-
template <>
87-
double PopPrimitive<double>(lua_State* L, int& index)
88-
{
89-
return static_cast<double>(lua_tonumber(L, index++));
90-
}
91-
9232
template <>
9333
bool PopPrimitive<bool>(lua_State* L, int& index)
9434
{
@@ -100,4 +40,12 @@ namespace lua
10040
{
10141
return lua_touserdata(L, index++);
10242
}
43+
44+
template<>
45+
lua_Number PopPrimitive<lua_Number>(lua_State* L, int& index)
46+
{
47+
return lua_tonumber(L, index++);
48+
}
49+
50+
// Int types aren't Poppable directly, because they need to be checked for under/overflow, NaN, inf
10351
} // namespace lua

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /