Skip to content

Commit fe46389

Browse files
committed
Properly raise div-by-zero errors in more cases under LSL
1 parent e609db7 commit fe46389

6 files changed

Lines changed: 63 additions & 7 deletions

File tree

VM/src/lvmexecute.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ inline bool luau_skipstep(uint8_t op)
208208
}
209209

210210

211-
static const char * const MATH_ERROR_STR = "Math error: division or modulus (possibly by 0) resulted in NaN";
211+
static const char * const MATH_ERROR_STR = "Math error: division or modulus by 0";
212212

213213
template<bool SingleStep>
214214
static void luau_execute(lua_State* L)
@@ -1774,9 +1774,8 @@ static void luau_execute(lua_State* L)
17741774
// ServerLua: ints not represented in here, they only support idiv.
17751775
const double res = nvalue(rb) / nvalue(rc);
17761776

1777-
// ServerLua: Any division that results in NaN is an error under Mono
1778-
// Generally this is div by zero, but there might be others.
1779-
if (LUAU_UNLIKELY(LUAU_IS_LSL_VM(L) && std::isnan(res)))
1777+
// ServerLua: In LSL (Mono), division by zero or a NaN result is an error.
1778+
if (LUAU_UNLIKELY(LUAU_IS_LSL_VM(L) && (nvalue(rc) == 0.0 || std::isnan(res))))
17801779
{
17811780
// VM protection is necessary here because PC may be invalid if we've
17821781
// not called `VM_PROTECT()` in this function yet.
@@ -2092,12 +2091,26 @@ static void luau_execute(lua_State* L)
20922091
// fast-path
20932092
if (LUAU_LIKELY(ttisnumber(rb)))
20942093
{
2095-
setnvalue(ra, nvalue(rb) / nvalue(kv));
2094+
const double res = nvalue(rb) / nvalue(kv);
2095+
2096+
// ServerLua: In LSL (Mono), division by zero or a NaN result is an error.
2097+
if (LUAU_UNLIKELY(LUAU_IS_LSL_VM(L) && (nvalue(kv) == 0.0 || std::isnan(res))))
2098+
{
2099+
VM_PROTECT(luaG_runerrorL(L, MATH_ERROR_STR));
2100+
}
2101+
2102+
setnvalue(ra, res);
20962103
VM_NEXT();
20972104
}
20982105
// ServerLua: int intentionally not handled, it uses idivk
20992106
else if (ttisvector(rb))
21002107
{
2108+
// ServerLua: In LSL (Mono), vector division by zero is a runtime error.
2109+
if (LUAU_UNLIKELY(LUAU_IS_LSL_VM(L) && nvalue(kv) == 0.0))
2110+
{
2111+
VM_PROTECT(luaG_runerrorL(L, MATH_ERROR_STR));
2112+
}
2113+
21012114
const float* vb = vvalue(rb);
21022115
float nc = cast_to(float, nvalue(kv));
21032116
setvvalue(ra, vb[0] / nc, vb[1] / nc, vb[2] / nc, vb[3] / nc);
@@ -3113,7 +3126,15 @@ static void luau_execute(lua_State* L)
31133126
// fast-path
31143127
if (LUAU_LIKELY(ttisnumber(rc)))
31153128
{
3116-
setnvalue(ra, nvalue(kv) / nvalue(rc));
3129+
const double res = nvalue(kv) / nvalue(rc);
3130+
3131+
// ServerLua: In LSL (Mono), division by zero or a NaN result is an error.
3132+
if (LUAU_UNLIKELY(LUAU_IS_LSL_VM(L) && (nvalue(rc) == 0.0 || std::isnan(res))))
3133+
{
3134+
VM_PROTECT(luaG_runerrorL(L, MATH_ERROR_STR));
3135+
}
3136+
3137+
setnvalue(ra, res);
31173138
VM_NEXT();
31183139
}
31193140
else if (ttisvector(rc))

tests/LSL.test.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1082,9 +1082,13 @@ TEST_CASE("Integer MulAssign Float Valid Contexts")
10821082
runConformance("mul_assign_valid.lsl");
10831083
}
10841084

1085-
TEST_CASE("Integer Division By Zero Error")
1085+
TEST_CASE("Division By Zero Error")
10861086
{
10871087
runConformance("div_by_zero.lsl", nullptr, nullptr, nullptr, "Math error");
1088+
runConformance("float_div_by_zero.lsl", nullptr, nullptr, nullptr, "Math error");
1089+
runConformance("vector_div_by_zero.lsl", nullptr, nullptr, nullptr, "Math error");
1090+
runConformance("zero_vector_div_by_zero.lsl", nullptr, nullptr, nullptr, "Math error");
1091+
runConformance("inf_div_inf.lsl", nullptr, nullptr, nullptr, "Math error");
10881092
}
10891093

10901094
TEST_CASE("Mono Strings")
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Test that float division by zero throws a runtime error
2+
default {
3+
state_entry() {
4+
float a = 1.0;
5+
float b = 0.0;
6+
float c = a / b; // This should error
7+
print((string)c);
8+
}
9+
}

tests/conformance/inf_div_inf.lsl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Test that Infinity / Infinity throws a runtime error (NaN result)
2+
default {
3+
state_entry() {
4+
float inf = (float)"inf";
5+
float result = inf / inf; // This should error
6+
print((string)result);
7+
}
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Test that vector division by zero throws a runtime error
2+
default {
3+
state_entry() {
4+
vector v = <1, 1, 1> / 0; // This should error
5+
print((string)v);
6+
}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Test that zero vector division by zero throws a runtime error
2+
default {
3+
state_entry() {
4+
vector v = <0, 0, 0> / 0; // This should error
5+
print((string)v);
6+
}
7+
}

0 commit comments

Comments
 (0)