diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-12-16 12:30:22 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2013-12-16 12:30:22 -0200 |
| commit | a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434 (patch) | |
| tree | b5193ced2c4516a8fe4c6a5af05e0d7d5c27d49c | |
| parent | 1a19893d6f8ee16944168a3f2c99002f70522f4c (diff) | |
| download | lua-a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434.tar.gz lua-a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434.tar.bz2 lua-a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434.zip | |
integer exponentiation with negative exponent is invalid
| -rw-r--r-- | lcode.c | 10 | ||||
| -rw-r--r-- | lobject.c | 9 | ||||
| -rw-r--r-- | lvm.c | 39 | ||||
| -rw-r--r-- | lvm.h | 4 |
4 files changed, 32 insertions, 30 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lcode.c,v 2.71 2013/06/25 18:57:18 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.72 2013/08/30 16:01:37 roberto Exp roberto $ |
| 3 | ** Code generator for Lua | 3 | ** Code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -754,12 +754,14 @@ static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { | |||
| 754 | TValue v1, v2, res; | 754 | TValue v1, v2, res; |
| 755 | lua_Integer i; | 755 | lua_Integer i; |
| 756 | if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2)) | 756 | if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2)) |
| 757 | return 0; | 757 | return 0; /* non-numeric operands */ |
| 758 | if (op == OP_IDIV && | 758 | if (op == OP_IDIV && |
| 759 | (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0)) | 759 | (!tointeger(&v1, &i) || !tointeger(&v2, &i) || i == 0)) |
| 760 | return 0; /* avoid division by 0 and conversion errors */ | 760 | return 0; /* avoid division by 0 and conversion errors */ |
| 761 | if (op == OP_MOD && ttisinteger(&v1) && ttisinteger(&v2) && ivalue(&v2) == 0) | 761 | if (ttisinteger(&v1) && ttisinteger(&v2) && /* for integer operations... */ |
| 762 | return 0; /* avoid module by 0 at compile time */ | 762 | ((op == OP_MOD && ivalue(&v2) == 0) || /* ...avoid module by 0... */ |
| 763 | (op == OP_POW && ivalue(&v2) < 0))) /* ...and negative exponents */ | ||
| 764 | return 0; | ||
| 763 | luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res); | 765 | luaO_arith(NULL, op - OP_ADD + LUA_OPADD, &v1, &v2, &res); |
| 764 | if (ttisinteger(&res)) { | 766 | if (ttisinteger(&res)) { |
| 765 | e1->k = VKINT; | 767 | e1->k = VKINT; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.c,v 2.67 2013/06/25 18:58:32 roberto Exp roberto $ | 2 | ** $Id: lobject.c,v 2.68 2013/07/10 17:15:12 roberto Exp roberto $ |
| 3 | ** Some generic functions over Lua objects | 3 | ** Some generic functions over Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -77,7 +77,7 @@ static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, | |||
| 77 | case LUA_OPSUB:return intop(-, v1, v2); | 77 | case LUA_OPSUB:return intop(-, v1, v2); |
| 78 | case LUA_OPMUL:return intop(*, v1, v2); | 78 | case LUA_OPMUL:return intop(*, v1, v2); |
| 79 | case LUA_OPMOD: return luaV_mod(L, v1, v2); | 79 | case LUA_OPMOD: return luaV_mod(L, v1, v2); |
| 80 | case LUA_OPPOW: return luaV_pow(v1, v2); | 80 | case LUA_OPPOW: return luaV_pow(L, v1, v2); |
| 81 | case LUA_OPUNM: return intop(-, 0, v1); | 81 | case LUA_OPUNM: return intop(-, 0, v1); |
| 82 | default: lua_assert(0); return 0; | 82 | default: lua_assert(0); return 0; |
| 83 | } | 83 | } |
| @@ -110,8 +110,7 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, | |||
| 110 | } | 110 | } |
| 111 | else { /* other operations */ | 111 | else { /* other operations */ |
| 112 | lua_Number n1; lua_Number n2; | 112 | lua_Number n1; lua_Number n2; |
| 113 | if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV && | 113 | if (ttisinteger(p1) && ttisinteger(p2) && op != LUA_OPDIV) { |
| 114 | (op != LUA_OPPOW || ivalue(p2) >= 0)) { | ||
| 115 | setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); | 114 | setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); |
| 116 | return; | 115 | return; |
| 117 | } | 116 | } |
| @@ -122,7 +121,7 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, | |||
| 122 | /* else go to the end */ | 121 | /* else go to the end */ |
| 123 | } | 122 | } |
| 124 | /* could not perform raw operation; try metmethod */ | 123 | /* could not perform raw operation; try metmethod */ |
| 125 | lua_assert(L != NULL); /* cannot fail when folding (compile time) */ | 124 | lua_assert(L != NULL); /* should not fail when folding (compile time) */ |
| 126 | luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD)); | 125 | luaT_trybinTM(L, p1, p2, res, cast(TMS, op - LUA_OPADD + TM_ADD)); |
| 127 | } | 126 | } |
| 128 | 127 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.179 2013/08/27 18:53:35 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.180 2013/08/29 13:49:57 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -333,8 +333,7 @@ lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y) { | |||
| 333 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ | 333 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ |
| 334 | if (y == 0) | 334 | if (y == 0) |
| 335 | luaG_runerror(L, "attempt to divide by zero"); | 335 | luaG_runerror(L, "attempt to divide by zero"); |
| 336 | else /* -1 */ | 336 | return intop(-, 0, x); /* y==-1; avoid overflow with 0x80000...//-1 */ |
| 337 | return intop(-, 0, x); /* avoid overflow with 0x80000... */ | ||
| 338 | } | 337 | } |
| 339 | else { | 338 | else { |
| 340 | lua_Integer d = x / y; /* perform division */ | 339 | lua_Integer d = x / y; /* perform division */ |
| @@ -350,8 +349,7 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { | |||
| 350 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ | 349 | if (cast_unsigned(y) + 1 <= 1U) { /* special cases: -1 or 0 */ |
| 351 | if (y == 0) | 350 | if (y == 0) |
| 352 | luaG_runerror(L, "attempt to perform 'n%%0'"); | 351 | luaG_runerror(L, "attempt to perform 'n%%0'"); |
| 353 | else /* -1 */ | 352 | return 0; /* y==-1; avoid overflow with 0x80000...%-1 */ |
| 354 | return 0; /* avoid overflow with 0x80000... */ | ||
| 355 | } | 353 | } |
| 356 | else { | 354 | else { |
| 357 | lua_Integer r = x % y; | 355 | lua_Integer r = x % y; |
| @@ -363,16 +361,21 @@ lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y) { | |||
| 363 | } | 361 | } |
| 364 | 362 | ||
| 365 | 363 | ||
| 366 | lua_Integer luaV_pow (lua_Integer x, lua_Integer y) { | 364 | lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y) { |
| 367 | lua_Integer r = 1; | 365 | if (y <= 0) { /* special cases: 0 or negative exponent */ |
| 368 | lua_assert(y >= 0); | 366 | if (y < 0) |
| 369 | if (y == 0) return r; | 367 | luaG_runerror(L, "integer exponentiation with negative exponent"); |
| 370 | for (; y > 1; y >>= 1) { | 368 | return 1; /* x^0 == 1 */ |
| 371 | if (y & 1) r = intop(*, r, x); | 369 | } |
| 372 | x = intop(*, x, x); | 370 | else { |
| 371 | lua_Integer r = 1; | ||
| 372 | for (; y > 1; y >>= 1) { | ||
| 373 | if (y & 1) r = intop(*, r, x); | ||
| 374 | x = intop(*, x, x); | ||
| 375 | } | ||
| 376 | r = intop(*, r, x); | ||
| 377 | return r; | ||
| 373 | } | 378 | } |
| 374 | r = intop(*, r, x); | ||
| 375 | return r; | ||
| 376 | } | 379 | } |
| 377 | 380 | ||
| 378 | 381 | ||
| @@ -685,11 +688,9 @@ void luaV_execute (lua_State *L) { | |||
| 685 | TValue *rb = RKB(i); | 688 | TValue *rb = RKB(i); |
| 686 | TValue *rc = RKC(i); | 689 | TValue *rc = RKC(i); |
| 687 | lua_Number nb; lua_Number nc; | 690 | lua_Number nb; lua_Number nc; |
| 688 | lua_Integer ic; | 691 | if (ttisinteger(rb) && ttisinteger(rc)) { |
| 689 | if (ttisinteger(rb) && ttisinteger(rc) && | 692 | lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); |
| 690 | (ic = ivalue(rc)) >= 0) { | 693 | setivalue(ra, luaV_pow(L, ib, ic)); |
| 691 | lua_Integer ib = ivalue(rb); | ||
| 692 | setivalue(ra, luaV_pow(ib, ic)); | ||
| 693 | } | 694 | } |
| 694 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { | 695 | else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { |
| 695 | setnvalue(ra, luai_numpow(L, nb, nc)); | 696 | setnvalue(ra, luai_numpow(L, nb, nc)); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.h,v 2.22 2013/04/29 17:12:50 roberto Exp roberto $ | 2 | ** $Id: lvm.h,v 2.23 2013/05/02 12:31:26 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -43,7 +43,7 @@ LUAI_FUNC void luaV_execute (lua_State *L); | |||
| 43 | LUAI_FUNC void luaV_concat (lua_State *L, int total); | 43 | LUAI_FUNC void luaV_concat (lua_State *L, int total); |
| 44 | LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); | 44 | LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); |
| 45 | LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); | 45 | LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); |
| 46 | LUAI_FUNC lua_Integer luaV_pow (lua_Integer x, lua_Integer y); | 46 | LUAI_FUNC lua_Integer luaV_pow (lua_State *L, lua_Integer x, lua_Integer y); |
| 47 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); | 47 | LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); |
| 48 | 48 | ||
| 49 | #endif | 49 | #endif |
