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
This commit is contained in:
parent
80bb6ccdc4
commit
9a9c7f2b7c
2 changed files with 33 additions and 8 deletions
|
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue