diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-02-07 13:39:54 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-02-07 13:39:54 -0300 |
commit | 0c9bec0d38ed3d2c45d7be4e764a0bcffef98be1 (patch) | |
tree | 05fd1ba56705dc0a1728e1bedda7961cc96414c1 | |
parent | c31d6774ac7db4cfbc548ce507ae65ab6036f873 (diff) | |
download | lua-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.c | 2 | ||||
-rw-r--r-- | ltable.c | 17 | ||||
-rw-r--r-- | ltablib.c | 6 | ||||
-rw-r--r-- | lua.h | 2 | ||||
-rw-r--r-- | manual/manual.of | 2 | ||||
-rw-r--r-- | testes/sort.lua | 29 |
6 files changed, 37 insertions, 21 deletions
@@ -781,7 +781,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { | |||
781 | } | 781 | } |
782 | 782 | ||
783 | 783 | ||
784 | LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { | 784 | LUA_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); |
@@ -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); |
@@ -59,8 +59,10 @@ static void checktab (lua_State *L, int arg, int what) { | |||
59 | 59 | ||
60 | 60 | ||
61 | static int tcreate (lua_State *L) { | 61 | static 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 | } |
@@ -268,7 +268,7 @@ LUA_API int (lua_rawget) (lua_State *L, int idx); | |||
268 | LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); | 268 | LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); |
269 | LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); | 269 | LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); |
270 | 270 | ||
271 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); | 271 | LUA_API void (lua_createtable) (lua_State *L, unsigned narr, unsigned nrec); |
272 | LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); | 272 | LUA_API void *(lua_newuserdatauv) (lua_State *L, size_t sz, int nuvalue); |
273 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); | 273 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); |
274 | LUA_API int (lua_getiuservalue) (lua_State *L, int idx, int n); | 274 | LUA_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 | ||
3240 | Creates a new empty table and pushes it onto the stack. | 3240 | Creates 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 | ||
4 | print "testing (parts of) table library" | 4 | print "testing (parts of) table library" |
5 | 5 | ||
6 | local maxI = math.maxinteger | ||
7 | local minI = math.mininteger | ||
8 | |||
9 | |||
10 | local function checkerror (msg, f, ...) | ||
11 | local s, err = pcall(f, ...) | ||
12 | assert(not s and string.find(err, msg)) | ||
13 | end | ||
14 | |||
15 | |||
6 | do print "testing 'table.create'" | 16 | do 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) | ||
26 | end | 40 | end |
27 | 41 | ||
28 | 42 | ||
@@ -30,15 +44,6 @@ print "testing unpack" | |||
30 | 44 | ||
31 | local unpack = table.unpack | 45 | local unpack = table.unpack |
32 | 46 | ||
33 | local maxI = math.maxinteger | ||
34 | local minI = math.mininteger | ||
35 | |||
36 | |||
37 | local function checkerror (msg, f, ...) | ||
38 | local s, err = pcall(f, ...) | ||
39 | assert(not s and string.find(err, msg)) | ||
40 | end | ||
41 | |||
42 | 47 | ||
43 | checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4) | 48 | checkerror("wrong number of arguments", table.insert, {}, 2, 3, 4) |
44 | 49 | ||