aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lapi.c2
-rw-r--r--lobject.c3
-rw-r--r--ltable.c50
-rw-r--r--ltable.h2
-rw-r--r--lvm.c2
-rw-r--r--testes/nextvar.lua12
6 files changed, 48 insertions, 23 deletions
diff --git a/lapi.c b/lapi.c
index 71405a25..0c88751a 100644
--- a/lapi.c
+++ b/lapi.c
@@ -440,7 +440,7 @@ LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) {
440 case LUA_VSHRSTR: return cast(lua_Unsigned, tsvalue(o)->shrlen); 440 case LUA_VSHRSTR: return cast(lua_Unsigned, tsvalue(o)->shrlen);
441 case LUA_VLNGSTR: return cast(lua_Unsigned, tsvalue(o)->u.lnglen); 441 case LUA_VLNGSTR: return cast(lua_Unsigned, tsvalue(o)->u.lnglen);
442 case LUA_VUSERDATA: return cast(lua_Unsigned, uvalue(o)->len); 442 case LUA_VUSERDATA: return cast(lua_Unsigned, uvalue(o)->len);
443 case LUA_VTABLE: return luaH_getn(hvalue(o)); 443 case LUA_VTABLE: return luaH_getn(L, hvalue(o));
444 default: return 0; 444 default: return 0;
445 } 445 }
446} 446}
diff --git a/lobject.c b/lobject.c
index 5c270b27..b558cfe0 100644
--- a/lobject.c
+++ b/lobject.c
@@ -31,7 +31,8 @@
31 31
32 32
33/* 33/*
34** Computes ceil(log2(x)) 34** Computes ceil(log2(x)), which is the smallest integer n such that
35** x <= (1 << n).
35*/ 36*/
36lu_byte luaO_ceillog2 (unsigned int x) { 37lu_byte luaO_ceillog2 (unsigned int x) {
37 static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */ 38 static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */
diff --git a/ltable.c b/ltable.c
index 1bea7aff..4017d8c7 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1220,24 +1220,36 @@ void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
1220 1220
1221/* 1221/*
1222** Try to find a boundary in the hash part of table 't'. From the 1222** Try to find a boundary in the hash part of table 't'. From the
1223** caller, we know that 'j' is zero or present and that 'j + 1' is 1223** caller, we know that 'asize + 1' is present. We want to find a larger
1224** present. We want to find a larger key that is absent from the 1224** key that is absent from the table, so that we can do a binary search
1225** table, so that we can do a binary search between the two keys to 1225** between the two keys to find a boundary. We keep doubling 'j' until
1226** find a boundary. We keep doubling 'j' until we get an absent index. 1226** we get an absent index. If the doubling would overflow, we try
1227** If the doubling would overflow, we try LUA_MAXINTEGER. If it is 1227** LUA_MAXINTEGER. If it is absent, we are ready for the binary search.
1228** absent, we are ready for the binary search. ('j', being max integer, 1228** ('j', being max integer, is larger or equal to 'i', but it cannot be
1229** is larger or equal to 'i', but it cannot be equal because it is 1229** equal because it is absent while 'i' is present.) Otherwise, 'j' is a
1230** absent while 'i' is present; so 'j > i'.) Otherwise, 'j' is a 1230** boundary. ('j + 1' cannot be a present integer key because it is not
1231** boundary. ('j + 1' cannot be a present integer key because it is 1231** a valid integer in Lua.)
1232** not a valid integer in Lua.) 1232** About 'rnd': If we used a fixed algorithm, a bad actor could fill
1233** a table with only the keys that would be probed, in such a way that
1234** a small table could result in a huge length. To avoid that, we use
1235** the state's seed as a source of randomness. For the first probe,
1236** we "randomly double" 'i' by adding to it a random number roughly its
1237** width.
1233*/ 1238*/
1234static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { 1239static lua_Unsigned hash_search (lua_State *L, Table *t, unsigned asize) {
1235 lua_Unsigned i; 1240 lua_Unsigned i = asize + 1; /* caller ensures t[i] is present */
1236 if (j == 0) j++; /* the caller ensures 'j + 1' is present */ 1241 unsigned rnd = G(L)->seed;
1237 do { 1242 int n = (asize > 0) ? luaO_ceillog2(asize) : 0; /* width of 'asize' */
1243 unsigned mask = (1u << n) - 1; /* 11...111 with the width of 'asize' */
1244 unsigned incr = (rnd & mask) + 1; /* first increment (at least 1) */
1245 lua_Unsigned j = (incr <= l_castS2U(LUA_MAXINTEGER) - i) ? i + incr : i + 1;
1246 rnd >>= n; /* used 'n' bits from 'rnd' */
1247 while (!hashkeyisempty(t, j)) { /* repeat until an absent t[j] */
1238 i = j; /* 'i' is a present index */ 1248 i = j; /* 'i' is a present index */
1239 if (j <= l_castS2U(LUA_MAXINTEGER) / 2) 1249 if (j <= l_castS2U(LUA_MAXINTEGER)/2 - 1) {
1240 j *= 2; 1250 j = j*2 + (rnd & 1); /* try again with 2j or 2j+1 */
1251 rnd >>= 1;
1252 }
1241 else { 1253 else {
1242 j = LUA_MAXINTEGER; 1254 j = LUA_MAXINTEGER;
1243 if (hashkeyisempty(t, j)) /* t[j] not present? */ 1255 if (hashkeyisempty(t, j)) /* t[j] not present? */
@@ -1245,7 +1257,7 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) {
1245 else /* weird case */ 1257 else /* weird case */
1246 return j; /* well, max integer is a boundary... */ 1258 return j; /* well, max integer is a boundary... */
1247 } 1259 }
1248 } while (!hashkeyisempty(t, j)); /* repeat until an absent t[j] */ 1260 }
1249 /* i < j && t[i] present && t[j] absent */ 1261 /* i < j && t[i] present && t[j] absent */
1250 while (j - i > 1u) { /* do a binary search between them */ 1262 while (j - i > 1u) { /* do a binary search between them */
1251 lua_Unsigned m = (i + j) / 2; 1263 lua_Unsigned m = (i + j) / 2;
@@ -1286,7 +1298,7 @@ static lua_Unsigned newhint (Table *t, unsigned hint) {
1286** If there is no array part, or its last element is non empty, the 1298** If there is no array part, or its last element is non empty, the
1287** border may be in the hash part. 1299** border may be in the hash part.
1288*/ 1300*/
1289lua_Unsigned luaH_getn (Table *t) { 1301lua_Unsigned luaH_getn (lua_State *L, Table *t) {
1290 unsigned asize = t->asize; 1302 unsigned asize = t->asize;
1291 if (asize > 0) { /* is there an array part? */ 1303 if (asize > 0) { /* is there an array part? */
1292 const unsigned maxvicinity = 4; 1304 const unsigned maxvicinity = 4;
@@ -1327,7 +1339,7 @@ lua_Unsigned luaH_getn (Table *t) {
1327 if (isdummy(t) || hashkeyisempty(t, asize + 1)) 1339 if (isdummy(t) || hashkeyisempty(t, asize + 1))
1328 return asize; /* 'asize + 1' is empty */ 1340 return asize; /* 'asize + 1' is empty */
1329 else /* 'asize + 1' is also non empty */ 1341 else /* 'asize + 1' is also non empty */
1330 return hash_search(t, asize); 1342 return hash_search(L, t, asize);
1331} 1343}
1332 1344
1333 1345
diff --git a/ltable.h b/ltable.h
index ca21e692..f3b7bc7e 100644
--- a/ltable.h
+++ b/ltable.h
@@ -173,7 +173,7 @@ LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned nasize);
173LUAI_FUNC lu_mem luaH_size (Table *t); 173LUAI_FUNC lu_mem luaH_size (Table *t);
174LUAI_FUNC void luaH_free (lua_State *L, Table *t); 174LUAI_FUNC void luaH_free (lua_State *L, Table *t);
175LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); 175LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);
176LUAI_FUNC lua_Unsigned luaH_getn (Table *t); 176LUAI_FUNC lua_Unsigned luaH_getn (lua_State *L, Table *t);
177 177
178 178
179#if defined(LUA_DEBUG) 179#if defined(LUA_DEBUG)
diff --git a/lvm.c b/lvm.c
index 74566888..cfdcf97a 100644
--- a/lvm.c
+++ b/lvm.c
@@ -722,7 +722,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
722 Table *h = hvalue(rb); 722 Table *h = hvalue(rb);
723 tm = fasttm(L, h->metatable, TM_LEN); 723 tm = fasttm(L, h->metatable, TM_LEN);
724 if (tm) break; /* metamethod? break switch to call it */ 724 if (tm) break; /* metamethod? break switch to call it */
725 setivalue(s2v(ra), l_castU2S(luaH_getn(h))); /* else primitive len */ 725 setivalue(s2v(ra), l_castU2S(luaH_getn(L, h))); /* else primitive len */
726 return; 726 return;
727 } 727 }
728 case LUA_VSHRSTR: { 728 case LUA_VSHRSTR: {
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index 03810a8e..7e5bed56 100644
--- a/testes/nextvar.lua
+++ b/testes/nextvar.lua
@@ -345,6 +345,18 @@ do
345 end 345 end
346end 346end
347 347
348
349do print("testing attack on table length")
350 local t = {}
351 local lim = math.floor(math.log(math.maxinteger, 2)) - 1
352 for i = lim, 0, -1 do
353 t[2^i] = true
354 end
355 assert(t[1 << lim])
356 -- next loop should not take forever
357 for i = 1, #t do end
358end
359
348local nofind = {} 360local nofind = {}
349 361
350 362