diff --git a/lundump.c b/lundump.c index d5fdc64b..7ab340cb 100644 --- a/lundump.c +++ b/lundump.c @@ -96,11 +96,12 @@ static lu_byte loadByte (LoadState *S) { static lua_Unsigned loadVarint (LoadState *S, lua_Unsigned limit) { lua_Unsigned x = 0; + lua_Unsigned limit_high = limit >> 7; + int limit_low = limit & 0x7f; int b; - limit >>= 7; do { b = loadByte(S); - if (x > limit) + if (x >= limit_high && (x > limit_high || (b & 0x7f) > limit_low)) error(S, "integer overflow"); x = (x << 7) | (b & 0x7f); } while ((b & 0x80) != 0); @@ -108,11 +109,6 @@ static lua_Unsigned loadVarint (LoadState *S, lua_Unsigned limit) { } -static size_t loadSize (LoadState *S) { - return cast_sizet(loadVarint(S, MAX_SIZE)); -} - - static int loadInt (LoadState *S) { return cast_int(loadVarint(S, cast_sizet(INT_MAX))); } @@ -137,16 +133,17 @@ static lua_Integer loadInteger (LoadState *S) { /* -** Load a nullable string into slot 'sl' from prototype 'p'. The -** assignment to the slot and the barrier must be performed before any -** possible GC activity, to anchor the string. (Both 'loadVector' and -** 'luaH_setint' can call the GC.) +** Load a nullable string into slot 'sl' from prototype 'p'. 'size' is +** either the string length + 1 or zero for a previously saved string. +** The assignment to the slot and the barrier must be performed before +** any possible GC activity, to anchor the string. (Both 'loadVector' +** and 'luaH_setint' can call the GC.) */ static void loadString (LoadState *S, Proto *p, TString **sl) { lua_State *L = S->L; TString *ts; TValue sv; - size_t size = loadSize(S); + size_t size = cast_sizet(loadVarint(S, MAX_SIZE - sizeof(TString) + 1)); if (size == 0) { /* previously saved string? */ lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */ TValue stv; @@ -160,7 +157,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { luaC_objbarrier(L, p, ts); return; /* do not save it again */ } - else if ((size -= 1) <= LUAI_MAXSHORTLEN) { /* short string? */ + else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ loadVector(S, buff, size + 1); /* load string into buffer */ *sl = ts = luaS_newlstr(L, buff, size); /* create string */ diff --git a/testes/code.lua b/testes/code.lua index 380ff70c..ba331d27 100644 --- a/testes/code.lua +++ b/testes/code.lua @@ -303,6 +303,7 @@ checkI(function () return 0xF0.0 | 0xCC.0 ~ 0xAA & 0xFD end, 0xF4) checkI(function () return ~(~kFF0 | kFF0) end, 0) checkI(function () return ~~-1024.0 end, -1024) checkI(function () return ((100 << k6) << -4) >> 2 end, 100) +checkK(function () return ~(-1 >> 1) end, math.mininteger) -- borders around MAXARG_sBx ((((1 << 17) - 1) >> 1) == 65535) local a = 17; local sbx = ((1 << a) - 1) >> 1 -- avoid folding diff --git a/testes/math.lua b/testes/math.lua index 54d19c40..ab74676a 100644 --- a/testes/math.lua +++ b/testes/math.lua @@ -385,6 +385,12 @@ do assert(minint == load("return " .. minint)()) assert(eqT(maxint, load("return " .. maxint)())) + -- limit for integer encoding in binary chunks + -- (~(-1 >> 1) is optimized by the compiler as minint, which is + -- then encoded in a binary chunk as max unsigned) + local f = string.dump(function () return ~(-1 >> 1) end) + assert(load(f)() == minint) + assert(eqT(10000000000000000000000.0, 10000000000000000000000)) assert(eqT(-10000000000000000000000.0, -10000000000000000000000)) end