diff --git a/ldump.c b/ldump.c index 79bb1dc9..a75b20d2 100644 --- a/ldump.c +++ b/ldump.c @@ -31,7 +31,7 @@ typedef struct { int strip; int status; Table *h; /* table to track saved strings */ - lua_Integer nstr; /* counter for counting saved strings */ + lua_Unsigned nstr; /* counter for counting saved strings */ } DumpState; @@ -87,12 +87,12 @@ static void dumpByte (DumpState *D, int y) { ** size for 'dumpVarint' buffer: each byte can store up to 7 bits. ** (The "+6" rounds up the division.) */ -#define DIBS ((l_numbits(size_t) + 6) / 7) +#define DIBS ((l_numbits(lua_Unsigned) + 6) / 7) /* ** Dumps an unsigned integer using the MSB Varint encoding */ -static void dumpVarint (DumpState *D, size_t x) { +static void dumpVarint (DumpState *D, lua_Unsigned x) { lu_byte buff[DIBS]; unsigned n = 1; buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ @@ -103,12 +103,13 @@ static void dumpVarint (DumpState *D, size_t x) { static void dumpSize (DumpState *D, size_t sz) { - dumpVarint(D, sz); + dumpVarint(D, cast(lua_Unsigned, sz)); } + static void dumpInt (DumpState *D, int x) { lua_assert(x >= 0); - dumpVarint(D, cast_sizet(x)); + dumpVarint(D, cast_uint(x)); } @@ -117,8 +118,16 @@ static void dumpNumber (DumpState *D, lua_Number x) { } +/* +** Signed integers are coded to keep small values small. (Coding -1 as +** 0xfff...fff would use too many bytes to save a quite common value.) +** A non-negative x is coded as 2x; a negative x is coded as -2x - 1. +** (0 => 0; -1 => 1; 1 => 2; -2 => 3; 2 => 4; ...) +*/ static void dumpInteger (DumpState *D, lua_Integer x) { - dumpVar(D, x); + lua_Unsigned cx = (x >= 0) ? 2u * l_castS2U(x) + : (2u * ~l_castS2U(x)) + 1; + dumpVarint(D, cx); } @@ -136,8 +145,8 @@ static void dumpString (DumpState *D, TString *ts) { TValue idx; int tag = luaH_getstr(D->h, ts, &idx); if (!tagisempty(tag)) { /* string already saved? */ - dumpSize(D, 1); /* reuse a saved string */ - dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */ + dumpVarint(D, 1); /* reuse a saved string */ + dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */ } else { /* must write and save the string */ TValue key, value; /* to save the string in the hash */ @@ -147,7 +156,7 @@ static void dumpString (DumpState *D, TString *ts) { dumpVector(D, s, size + 1); /* include ending '\0' */ D->nstr++; /* one more saved string */ setsvalue(D->L, &key, ts); /* the string is the key */ - setivalue(&value, D->nstr); /* its index is the value */ + setivalue(&value, l_castU2S(D->nstr)); /* its index is the value */ luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ /* integer value does not need barrier */ } diff --git a/lundump.c b/lundump.c index b69ec336..10528987 100644 --- a/lundump.c +++ b/lundump.c @@ -37,7 +37,7 @@ typedef struct { const char *name; Table *h; /* list for string reuse */ size_t offset; /* current position relative to beginning of dump */ - lua_Integer nstr; /* number of strings in the list */ + lua_Unsigned nstr; /* number of strings in the list */ lu_byte fixed; /* dump is fixed in memory */ } LoadState; @@ -94,8 +94,8 @@ static lu_byte loadByte (LoadState *S) { } -static size_t loadVarint (LoadState *S, size_t limit) { - size_t x = 0; +static lua_Unsigned loadVarint (LoadState *S, lua_Unsigned limit) { + lua_Unsigned x = 0; int b; limit >>= 7; do { @@ -127,9 +127,12 @@ static lua_Number loadNumber (LoadState *S) { static lua_Integer loadInteger (LoadState *S) { - lua_Integer x; - loadVar(S, x); - return x; + lua_Unsigned cx = loadVarint(S, LUA_MAXUNSIGNED); + /* decode unsigned to signed */ + if ((cx & 1) != 0) + return l_castU2S(~(cx >> 1)); + else + return l_castU2S(cx >> 1); } @@ -149,9 +152,9 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { return; } else if (size == 1) { /* previously saved string? */ - lua_Integer idx = cast_st2S(loadSize(S)); /* get its index */ + lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */ TValue stv; - luaH_getint(S->h, idx, &stv); /* get its value */ + luaH_getint(S->h, l_castU2S(idx), &stv); /* get its value */ *sl = ts = tsvalue(&stv); luaC_objbarrier(L, p, ts); return; /* do not save it again */ @@ -175,7 +178,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { /* add string to list of saved strings */ S->nstr++; setsvalue(L, &sv, ts); - luaH_setint(L, S->h, S->nstr, &sv); + luaH_setint(L, S->h, l_castU2S(S->nstr), &sv); luaC_objbarrierback(L, obj2gco(S->h), ts); } diff --git a/testes/code.lua b/testes/code.lua index 633f4896..380ff70c 100644 --- a/testes/code.lua +++ b/testes/code.lua @@ -482,5 +482,23 @@ do -- basic check for SETLIST assert(count == 1) end + +do print("testing code for integer limits") + local function checkints (n) + local source = string.format( + "local a = {[true] = 0X%x}; return a[true]", n) + local f = assert(load(source)) + checkKlist(f, {n}) + assert(f() == n) + f = load(string.dump(f)) + assert(f() == n) + end + + checkints(math.maxinteger) + checkints(math.mininteger) + checkints(-1) + +end + print 'OK'