aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-02-07 13:39:54 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-02-07 13:39:54 -0300
commit0c9bec0d38ed3d2c45d7be4e764a0bcffef98be1 (patch)
tree05fd1ba56705dc0a1728e1bedda7961cc96414c1
parentc31d6774ac7db4cfbc548ce507ae65ab6036f873 (diff)
downloadlua-0c9bec0d38ed3d2c45d7be4e764a0bcffef98be1.tar.gz
lua-0c9bec0d38ed3d2c45d7be4e764a0bcffef98be1.tar.bz2
lua-0c9bec0d38ed3d2c45d7be4e764a0bcffef98be1.zip
Better handling of size limit when resizing a table
Avoid silent conversions from int to unsigned int when calling 'luaH_resize'; avoid silent conversions from lua_Integer to int in 'table.create'; MAXASIZE corrected for the new implementation of arrays; 'luaH_resize' checks explicitly whether new size respects MAXASIZE. (Even constructors were bypassing that check.)
Diffstat (limited to '')
-rw-r--r--lapi.c2
-rw-r--r--ltable.c17
-rw-r--r--ltablib.c6
-rw-r--r--lua.h2
-rw-r--r--manual/manual.of2
-rw-r--r--testes/sort.lua29
6 files changed, 37 insertions, 21 deletions
diff --git a/lapi.c b/lapi.c
index bb76b15a..69b890cd 100644
--- a/lapi.c
+++ b/lapi.c
@@ -781,7 +781,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) {
781} 781}
782 782
783 783
784LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { 784LUA_API void lua_createtable (lua_State *L, unsigned narray, unsigned nrec) {
785 Table *t; 785 Table *t;
786 lua_lock(L); 786 lua_lock(L);
787 t = luaH_new(L); 787 t = luaH_new(L);
diff --git a/ltable.c b/ltable.c
index 353e567b..b86e2281 100644
--- a/ltable.c
+++ b/ltable.c
@@ -61,18 +61,25 @@ typedef union {
61 61
62 62
63/* 63/*
64** MAXABITS is the largest integer such that MAXASIZE fits in an 64** MAXABITS is the largest integer such that 2^MAXABITS fits in an
65** unsigned int. 65** unsigned int.
66*/ 66*/
67#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1) 67#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1)
68 68
69 69
70/* 70/*
71** MAXASIZEB is the maximum number of elements in the array part such
72** that the size of the array fits in 'size_t'.
73*/
74#define MAXASIZEB ((MAX_SIZET/sizeof(ArrayCell)) * NM)
75
76
77/*
71** MAXASIZE is the maximum size of the array part. It is the minimum 78** MAXASIZE is the maximum size of the array part. It is the minimum
72** between 2^MAXABITS and the maximum size that, measured in bytes, 79** between 2^MAXABITS and MAXASIZEB.
73** fits in a 'size_t'.
74*/ 80*/
75#define MAXASIZE luaM_limitN(1u << MAXABITS, TValue) 81#define MAXASIZE \
82 (((1u << MAXABITS) < MAXASIZEB) ? (1u << MAXABITS) : cast_uint(MAXASIZEB))
76 83
77/* 84/*
78** MAXHBITS is the largest integer such that 2^MAXHBITS fits in a 85** MAXHBITS is the largest integer such that 2^MAXHBITS fits in a
@@ -663,6 +670,8 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
663 Table newt; /* to keep the new hash part */ 670 Table newt; /* to keep the new hash part */
664 unsigned int oldasize = setlimittosize(t); 671 unsigned int oldasize = setlimittosize(t);
665 ArrayCell *newarray; 672 ArrayCell *newarray;
673 if (newasize > MAXASIZE)
674 luaG_runerror(L, "table overflow");
666 /* create new hash part with appropriate size into 'newt' */ 675 /* create new hash part with appropriate size into 'newt' */
667 newt.flags = 0; 676 newt.flags = 0;
668 setnodevector(L, &newt, nhsize); 677 setnodevector(L, &newt, nhsize);
diff --git a/ltablib.c b/ltablib.c
index c8838963..2ba31a4f 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -59,8 +59,10 @@ static void checktab (lua_State *L, int arg, int what) {
59 59
60 60
61static int tcreate (lua_State *L) { 61static int tcreate (lua_State *L) {
62 int sizeseq = (int)luaL_checkinteger(L, 1); 62 lua_Unsigned sizeseq = (lua_Unsigned)luaL_checkinteger(L, 1);
63 int sizerest = (int)luaL_optinteger(L, 2, 0); 63 lua_Unsigned sizerest = (lua_Unsigned)luaL_optinteger(L, 2, 0);
64 luaL_argcheck(L, sizeseq <= UINT_MAX, 1, "out of range");
65 luaL_argcheck(L, sizerest <= UINT_MAX, 2, "out of range");
64 lua_createtable(L, sizeseq, sizerest); 66 lua_createtable(L, sizeseq, sizerest);
65 return 1; 67 return 1;
66} 68}
diff --git a/lua.h b/lua.h
index 58f31646..b8e0c571 100644
--- a/lua.h
+++ b/lua.h
@@ -268,7 +268,7 @@ LUA_API int (lua_rawget) (lua_State *L, int idx);
268LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); 268LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n);
269LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); 269LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p);
270 270
271LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); 271LUA_API void (lua_createtable) (lua_State *L, unsigned narr, unsigned nrec);
272LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); 272LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue);
273LUA_API int (lua_getmetatable) (lua_State *L, int objindex); 273LUA_API int (lua_getmetatable) (lua_State *L, int objindex);
274LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n); 274LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n);
diff --git a/manual/manual.of b/manual/manual.of
index aaaf15b7..cdd54f66 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -3234,7 +3234,7 @@ Values at other positions are not affected.
3234 3234
3235} 3235}
3236 3236
3237@APIEntry{void lua_createtable (lua_State *L, int nseq, int nrec);| 3237@APIEntry{void lua_createtable (lua_State *L, unsigned nseq, unsigned nrec);|
3238@apii{0,1,m} 3238@apii{0,1,m}
3239 3239
3240Creates a new empty table and pushes it onto the stack. 3240Creates a new empty table and pushes it onto the stack.
diff --git a/testes/sort.lua b/testes/sort.lua
index 7e566a5a..442b3129 100644
--- a/testes/sort.lua
+++ b/testes/sort.lua
@@ -3,19 +3,30 @@
3 3
4print "testing (parts of) table library" 4print "testing (parts of) table library"
5 5
6local maxI = math.maxinteger
7local minI = math.mininteger
8
9
10local function checkerror (msg, f, ...)
11 local s, err = pcall(f, ...)
12 assert(not s and string.find(err, msg))
13end
14
15
6do print "testing 'table.create'" 16do print "testing 'table.create'"
17 local N = 10000
7 collectgarbage() 18 collectgarbage()
8 local m = collectgarbage("count") * 1024 19 local m = collectgarbage("count") * 1024
9 local t = table.create(10000) 20 local t = table.create(N)
10 local memdiff = collectgarbage("count") * 1024 - m 21 local memdiff = collectgarbage("count") * 1024 - m
11 assert(memdiff > 10000 * 4) 22 assert(memdiff > N * 4)
12 for i = 1, 20 do 23 for i = 1, 20 do
13 assert(#t == i - 1) 24 assert(#t == i - 1)
14 t[i] = 0 25 t[i] = 0
15 end 26 end
16 for i = 1, 20 do t[#t + 1] = i * 10 end 27 for i = 1, 20 do t[#t + 1] = i * 10 end
17 assert(#t == 40 and t[39] == 190) 28 assert(#t == 40 and t[39] == 190)
18 assert(not T or T.querytab(t) == 10000) 29 assert(not T or T.querytab(t) == N)
19 t = nil 30 t = nil
20 collectgarbage() 31 collectgarbage()
21 m = collectgarbage("count") * 1024 32 m = collectgarbage("count") * 1024
@@ -23,6 +34,9 @@ do print "testing 'table.create'"
23 memdiff = collectgarbage("count") * 1024 - m 34 memdiff = collectgarbage("count") * 1024 - m
24 assert(memdiff > 1024 * 12) 35 assert(memdiff > 1024 * 12)
25 assert(not T or select(2, T.querytab(t)) == 1024) 36 assert(not T or select(2, T.querytab(t)) == 1024)
37
38 checkerror("table overflow", table.create, (1<<31) + 1)
39 checkerror("table overflow", table.create, 0, (1<<31) + 1)
26end 40end
27 41
28 42
@@ -30,15 +44,6 @@ print "testing unpack"
30 44
31local unpack = table.unpack 45local unpack = table.unpack
32 46
33local maxI = math.maxinteger
34local minI = math.mininteger
35
36
37local function checkerror (msg, f, ...)
38 local s, err = pcall(f, ...)
39 assert(not s and string.find(err, msg))
40end
41
42 47
43checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4) 48checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4)
44 49