aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ltablib.c11
-rw-r--r--testes/sort.lua13
2 files changed, 20 insertions, 4 deletions
diff --git a/ltablib.c b/ltablib.c
index 46ecb5e0..15c3c09f 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -42,15 +42,17 @@ static int checkfield (lua_State *L, const char *key, int n) {
42 42
43/* 43/*
44** Check that 'arg' either is a table or can behave like one (that is, 44** Check that 'arg' either is a table or can behave like one (that is,
45** has a metatable with the required metamethods) 45** has a metatable with the required metamethods).
46*/ 46*/
47static void checktab (lua_State *L, int arg, int what) { 47static void checktab (lua_State *L, int arg, int what) {
48 if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ 48 int tp = lua_type(L, arg);
49 if (tp != LUA_TTABLE) { /* is it not a table? */
49 int n = 1; /* number of elements to pop */ 50 int n = 1; /* number of elements to pop */
50 if (lua_getmetatable(L, arg) && /* must have metatable */ 51 if (lua_getmetatable(L, arg) && /* must have metatable */
51 (!(what & TAB_R) || checkfield(L, "__index", ++n)) && 52 (!(what & TAB_R) || checkfield(L, "__index", ++n)) &&
52 (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && 53 (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) &&
53 (!(what & TAB_L) || checkfield(L, "__len", ++n))) { 54 (!(what & TAB_L) || /* strings don't need '__len' to have a length */
55 tp == LUA_TSTRING || checkfield(L, "__len", ++n))) {
54 lua_pop(L, n); /* pop metatable and tested metamethods */ 56 lua_pop(L, n); /* pop metatable and tested metamethods */
55 } 57 }
56 else 58 else
@@ -204,8 +206,9 @@ static int tpack (lua_State *L) {
204 206
205static int tunpack (lua_State *L) { 207static int tunpack (lua_State *L) {
206 lua_Unsigned n; 208 lua_Unsigned n;
209 lua_Integer len = aux_getn(L, 1, TAB_R);
207 lua_Integer i = luaL_optinteger(L, 2, 1); 210 lua_Integer i = luaL_optinteger(L, 2, 1);
208 lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); 211 lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, len);
209 if (i > e) return 0; /* empty range */ 212 if (i > e) return 0; /* empty range */
210 n = l_castS2U(e) - l_castS2U(i); /* number of elements minus 1 */ 213 n = l_castS2U(e) - l_castS2U(i); /* number of elements minus 1 */
211 if (l_unlikely(n >= (unsigned int)INT_MAX || 214 if (l_unlikely(n >= (unsigned int)INT_MAX ||
diff --git a/testes/sort.lua b/testes/sort.lua
index b0127660..92aaca3c 100644
--- a/testes/sort.lua
+++ b/testes/sort.lua
@@ -72,6 +72,19 @@ assert(a==1 and x==nil)
72a,x = unpack({1,2}, 1, 1) 72a,x = unpack({1,2}, 1, 1)
73assert(a==1 and x==nil) 73assert(a==1 and x==nil)
74 74
75
76do -- unpack with non-tables
77 local debug = require"debug"
78 local oldmt = debug.getmetatable(0)
79 local str = "hello"
80 debug.setmetatable(0,
81 { __len = function () return #str end,
82 __index = function (_, i) return string.sub(str, i, i) end})
83 assert(table.concat({table.unpack(0)}) == str)
84 debug.setmetatable(0, oldmt) -- restore original metatable for numbers
85end
86
87
75do 88do
76 local maxi = (1 << 31) - 1 -- maximum value for an int (usually) 89 local maxi = (1 << 31) - 1 -- maximum value for an int (usually)
77 local mini = -(1 << 31) -- minimum value for an int (usually) 90 local mini = -(1 << 31) -- minimum value for an int (usually)