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 /lvm.c | |
parent | 1a19893d6f8ee16944168a3f2c99002f70522f4c (diff) | |
download | lua-a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434.tar.gz lua-a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434.tar.bz2 lua-a8f8c7fd80a5c7e630fd4bf7f858d05024f6b434.zip |
integer exponentiation with negative exponent is invalid
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 39 |
1 files changed, 20 insertions, 19 deletions
@@ -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)); |