From 9a9c7f2b7c63a9db203084a3485988c07f17b86c Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Mon, 5 Feb 2018 07:28:08 +0100 Subject: Fix lua failure to catch divide by zero and NaN exceptions I can only assume in the course of the original conversion to fixed point math in RbLua the fact that division by zero and NaN handling was to be caught as a graceful exception by the floating point handler was overlooked. As a result lua doesn't handle these exceptions and instead results in a panic on the device. This patch fixes this handling in the lexer for compile time Inf and Nan results and in the luavm for runtime division by zero (Inf) I missed the runtime exception of n%0 added checks for that as well.. Change-Id: I7746c087ea93678e5875f15ec6fe3f29f26bdb31 --- apps/plugins/lua/lcode.c | 13 ++++++++----- apps/plugins/lua/lvm.c | 28 +++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'apps') diff --git a/apps/plugins/lua/lcode.c b/apps/plugins/lua/lcode.c index cff626b7fa..cc26ac7521 100644 --- a/apps/plugins/lua/lcode.c +++ b/apps/plugins/lua/lcode.c @@ -642,26 +642,27 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { case OP_SUB: r = luai_numsub(v1, v2); break; case OP_MUL: r = luai_nummul(v1, v2); break; case OP_DIV: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + if (v2 == 0) return -1; /* do not attempt to divide by 0 */ r = luai_numdiv(v1, v2); break; case OP_MOD: - if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + if (v2 == 0) return -1; /* do not attempt to divide by 0 */ r = luai_nummod(v1, v2); break; case OP_POW: r = luai_numpow(v1, v2); break; case OP_UNM: r = luai_numunm(v1); break; case OP_LEN: return 0; /* no constant folding for 'len' */ default: lua_assert(0); r = 0; break; } - if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ + if (luai_numisnan(r)) return -2; /* do not attempt to produce NaN */ e1->u.nval = r; return 1; } static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { - if (constfolding(op, e1, e2)) + int resf = constfolding(op, e1, e2); + if (resf > 0) return; - else { + else if (resf == 0) { int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; int o1 = luaK_exp2RK(fs, e1); if (o1 > o2) { @@ -675,6 +676,8 @@ static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); e1->k = VRELOCABLE; } + else + luaX_syntaxerror(fs->ls, "Inf or NaN"); } diff --git a/apps/plugins/lua/lvm.c b/apps/plugins/lua/lvm.c index ee3256ab94..acce53a858 100644 --- a/apps/plugins/lua/lvm.c +++ b/apps/plugins/lua/lvm.c @@ -480,13 +480,35 @@ void luaV_execute (lua_State *L, int nexeccalls) { continue; } case OP_DIV: { - arith_op(luai_numdiv, TM_DIV); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + lua_Number nb = nvalue(rb), nc = nvalue(rc); + if (nc == 0) + luaG_typeerror(L, rc, "divide by zero"); + + setnvalue(ra, luai_numdiv(nb, nc)); + } + else + Protect(Arith(L, ra, rb, rc, TM_DIV)); + continue; } case OP_MOD: { - arith_op(luai_nummod, TM_MOD); + TValue *rb = RKB(i); + TValue *rc = RKC(i); + if (ttisnumber(rb) && ttisnumber(rc)) { + lua_Number nb = nvalue(rb), nc = nvalue(rc); + if (nc == 0) + luaG_typeerror(L, rc, "perform 'n%0'"); + + setnvalue(ra, luai_nummod(nb, nc)); + } + else + Protect(Arith(L, ra, rb, rc, TM_MOD)); + continue; - } + } case OP_POW: { arith_op(luai_numpow, TM_POW); continue; -- cgit v1.2.3