From a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 16 Dec 2013 12:30:22 -0200 Subject: [PATCH] integer exponentiation with negative exponent is invalid --- lcode.c | 10 ++++++---- lobject.c | 9 ++++----- lvm.c | 39 ++++++++++++++++++++------------------- lvm.h | 4 ++-- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/lcode.c b/lcode.c index 4dd823f2..34dadd1f 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.71 2013/06/25 18:57:18 roberto Exp roberto $ +** $Id: lcode.c,v 2.72 2013/08/30 16:01:37 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -754,12 +754,14 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { TValue v1, v2, res; lua_Integer i; if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2)) - return 0; + return 0; /* non-numeric operands */ if (op == OP_IDIV && (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0)) return 0; /* avoid division by 0 and conversion errors */ - if (op == OP_MOD && ttisinteger(&v1) && ttisinteger(&v2) && ivalue(&v2) == 0) - return 0; /* avoid module by 0 at compile time */ + if (ttisinteger(&v1) && ttisinteger(&v2) && /* for integer operations... */ + ((op == OP_MOD && ivalue(&v2) == 0) || /* ...avoid module by 0... */ + (op == OP_POW && ivalue(&v2) < 0))) /* ...and negative exponents */ + return 0; luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res); if (ttisinteger(&res)) { e1->k = VKINT; diff --git a/lobject.c b/lobject.c index 92721332..32f4a191 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 2.67 2013/06/25 18:58:32 roberto Exp roberto $ +** $Id: lobject.c,v 2.68 2013/07/10 17:15:12 roberto Exp roberto $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -77,7 +77,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, case LUA_OPSUB:return intop(-, v1, v2); case LUA_OPMUL:return intop(*, v1, v2); case LUA_OPMOD: return luaV_mod(L, v1, v2); - case LUA_OPPOW: return luaV_pow(v1, v2); + case LUA_OPPOW: return luaV_pow(L, v1, v2); case LUA_OPUNM: return intop(-, 0, v1); default: lua_assert(0); return 0; } @@ -110,8 +110,7 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, } else { /* other operations */ lua_Number n1; lua_Number n2; - if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV && - (op != LUA_OPPOW || ivalue(p2) >= 0)) { + if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV) { setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); return; } @@ -122,7 +121,7 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, /* else go to the end */ } /* could not perform raw operation; try metmethod */ - lua_assert(L != NULL); /* cannot fail when folding (compile time) */ + lua_assert(L != NULL); /* should not fail when folding (compile time) */ luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD)); } diff --git a/lvm.c b/lvm.c index cba196b0..354f40d9 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.179 2013/08/27 18:53:35 roberto Exp roberto $ +** $Id: lvm.c,v 2.180 2013/08/29 13:49:57 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -333,8 +333,7 @@ lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ if (y == 0) luaG_runerror(L, "attempt to divide by zero"); - else /* -1 */ - return intop(-, 0, x); /* avoid overflow with 0x80000... */ + return intop(-, 0, x); /* y==-1; avoid overflow with 0x80000...//-1 */ } else { lua_Integer d = x / y; /* perform division */ @@ -350,8 +349,7 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ if (y == 0) luaG_runerror(L, "attempt to perform 'n%%0'"); - else /* -1 */ - return 0; /* avoid overflow with 0x80000... */ + return 0; /* y==-1; avoid overflow with 0x80000...%-1 */ } else { lua_Integer r = x % y; @@ -363,16 +361,21 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { } -lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { - lua_Integer r = 1; - lua_assert(y >= 0); - if (y == 0) return r; - for (; y > 1; y >>= 1) { - if (y & 1) r = intop(*, r, x); - x = intop(*, x, x); +lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y) { + if (y <= 0) { /* special cases: 0 or negative exponent */ + if (y < 0) + luaG_runerror(L, "integer exponentiation with negative exponent"); + return 1; /* x^0 == 1 */ + } + else { + lua_Integer r = 1; + for (; y > 1; y >>= 1) { + if (y & 1) r = intop(*, r, x); + x = intop(*, x, x); + } + r = intop(*, r, x); + return r; } - r = intop(*, r, x); - return r; } @@ -685,11 +688,9 @@ void luaV_execute (lua_State *L) { TValue *rb = RKB(i); TValue *rc = RKC(i); lua_Number nb; lua_Number nc; - lua_Integer ic; - if (ttisinteger(rb) && ttisinteger(rc) && - (ic = ivalue(rc)) >= 0) { - lua_Integer ib = ivalue(rb); - setivalue(ra, luaV_pow(ib, ic)); + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_pow(L, ib, ic)); } else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { setnvalue(ra, luai_numpow(L, nb, nc)); diff --git a/lvm.h b/lvm.h index b352e8ed..56713c83 100644 --- a/lvm.h +++ b/lvm.h @@ -1,5 +1,5 @@ /* -** $Id: lvm.h,v 2.22 2013/04/29 17:12:50 roberto Exp roberto $ +** $Id: lvm.h,v 2.23 2013/05/02 12:31:26 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -43,7 +43,7 @@ LUAI_FUNC void luaV_execute (lua_State *L); LUAI_FUNC void luaV_concat (lua_State *L, int total); LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); -LUAI_FUNC lua_Integer luaV_pow (lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y); LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); #endif