forked from pool/lua54
31ade7d3fc
- Update upstream-bugs.patch and upstream-bugs-test.patch to fix bugs 9,10,12 for build and tests respectively. Bug 11 changes interface of luaD_pretailcall. OBS-URL: https://build.opensuse.org/request/show/943227 OBS-URL: https://build.opensuse.org/package/show/devel:languages:lua/lua54?expand=0&rev=40
371 lines
10 KiB
Diff
371 lines
10 KiB
Diff
diff --git a/testes/locals.lua b/testes/locals.lua
|
|
index 2c67edbdb..6aad5d253 100644
|
|
--- a/locals.lua
|
|
+++ b/locals.lua
|
|
@@ -335,6 +335,29 @@ do
|
|
end
|
|
|
|
|
|
+do
|
|
+ -- bug in 5.4.3: previous condition (calls cannot be tail in the
|
|
+ -- scope of to-be-closed variables) must be valid for tbc variables
|
|
+ -- created by 'for' loops.
|
|
+
|
|
+ local closed = false
|
|
+
|
|
+ local function foo ()
|
|
+ return function () return true end, 0, 0,
|
|
+ func2close(function () closed = true end)
|
|
+ end
|
|
+
|
|
+ local function tail() return closed end
|
|
+
|
|
+ local function foo1 ()
|
|
+ for k in foo() do return tail() end
|
|
+ end
|
|
+
|
|
+ assert(foo1() == false)
|
|
+ assert(closed == true)
|
|
+end
|
|
+
|
|
+
|
|
do print("testing errors in __close")
|
|
|
|
-- original error is in __close
|
|
diff --git a/testes/locals.lua b/testes/locals.lua
|
|
index 6aad5d253..6151f64d0 100644
|
|
--- a/locals.lua
|
|
+++ b/locals.lua
|
|
@@ -813,6 +813,65 @@ do
|
|
end
|
|
|
|
|
|
+do
|
|
+ -- yielding inside closing metamethods while returning
|
|
+ -- (bug in 5.4.3)
|
|
+
|
|
+ local extrares -- result from extra yield (if any)
|
|
+
|
|
+ local function check (body, extra, ...)
|
|
+ local t = table.pack(...) -- expected returns
|
|
+ local co = coroutine.wrap(body)
|
|
+ if extra then
|
|
+ extrares = co() -- runs until first (extra) yield
|
|
+ end
|
|
+ local res = table.pack(co()) -- runs until yield inside '__close'
|
|
+ assert(res.n == 2 and res[2] == nil)
|
|
+ local res2 = table.pack(co()) -- runs until end of function
|
|
+ assert(res2.n == t.n)
|
|
+ for i = 1, #t do
|
|
+ if t[i] == "x" then
|
|
+ assert(res2[i] == res[1]) -- value that was closed
|
|
+ else
|
|
+ assert(res2[i] == t[i])
|
|
+ end
|
|
+ end
|
|
+ end
|
|
+
|
|
+ local function foo ()
|
|
+ local x <close> = func2close(coroutine.yield)
|
|
+ local extra <close> = func2close(function (self)
|
|
+ assert(self == extrares)
|
|
+ coroutine.yield(100)
|
|
+ end)
|
|
+ extrares = extra
|
|
+ return table.unpack{10, x, 30}
|
|
+ end
|
|
+ check(foo, true, 10, "x", 30)
|
|
+ assert(extrares == 100)
|
|
+
|
|
+ local function foo ()
|
|
+ local x <close> = func2close(coroutine.yield)
|
|
+ return
|
|
+ end
|
|
+ check(foo, false)
|
|
+
|
|
+ local function foo ()
|
|
+ local x <close> = func2close(coroutine.yield)
|
|
+ local y, z = 20, 30
|
|
+ return x
|
|
+ end
|
|
+ check(foo, false, "x")
|
|
+
|
|
+ local function foo ()
|
|
+ local x <close> = func2close(coroutine.yield)
|
|
+ local extra <close> = func2close(coroutine.yield)
|
|
+ return table.unpack({}, 1, 100) -- 100 nils
|
|
+ end
|
|
+ check(foo, true, table.unpack({}, 1, 100))
|
|
+
|
|
+end
|
|
+
|
|
do
|
|
-- yielding inside closing metamethods after an error
|
|
|
|
diff --git a/testes/locals.lua b/testes/locals.lua
|
|
index 6151f64d0..62a88df57 100644
|
|
--- a/locals.lua
|
|
+++ b/locals.lua
|
|
@@ -187,6 +187,8 @@ do -- constants
|
|
checkro("y", "local x, y <const>, z = 10, 20, 30; x = 11; y = 12")
|
|
checkro("x", "local x <const>, y, z <const> = 10, 20, 30; x = 11")
|
|
checkro("z", "local x <const>, y, z <const> = 10, 20, 30; y = 10; z = 11")
|
|
+ checkro("foo", "local foo <const> = 10; function foo() end")
|
|
+ checkro("foo", "local foo <const> = {}; function foo() end")
|
|
|
|
checkro("z", [[
|
|
local a, z <const>, b = 10;
|
|
diff --git a/testes/bitwise.lua b/testes/bitwise.lua
|
|
index 59781f5df..9509f7f04 100644
|
|
--- a/bitwise.lua
|
|
+++ b/bitwise.lua
|
|
@@ -45,6 +45,11 @@ assert(-1 >> numbits == 0 and
|
|
-1 << numbits == 0 and
|
|
-1 << -numbits == 0)
|
|
|
|
+assert(1 >> math.mininteger == 0)
|
|
+assert(1 >> math.maxinteger == 0)
|
|
+assert(1 << math.mininteger == 0)
|
|
+assert(1 << math.maxinteger == 0)
|
|
+
|
|
assert((2^30 - 1) << 2^30 == 0)
|
|
assert((2^30 - 1) >> 2^30 == 0)
|
|
|
|
diff --git a/testes/errors.lua b/testes/errors.lua
|
|
index 825f37c29..a7dc479a2 100644
|
|
--- a/errors.lua
|
|
+++ b/errors.lua
|
|
@@ -228,6 +228,22 @@ do -- named objects (field '__name')
|
|
checkmessage("return {} < XX", "table with My Type")
|
|
checkmessage("return XX < io.stdin", "My Type with FILE*")
|
|
_G.XX = nil
|
|
+
|
|
+ if T then -- extra tests for 'luaL_tolstring'
|
|
+ -- bug in 5.4.3; 'luaL_tolstring' with negative indices
|
|
+ local x = setmetatable({}, {__name="TABLE"})
|
|
+ assert(T.testC("Ltolstring -1; return 1", x) == tostring(x))
|
|
+
|
|
+ local a, b = T.testC("pushint 10; Ltolstring -2; return 2", x)
|
|
+ assert(a == 10 and b == tostring(x))
|
|
+
|
|
+ setmetatable(x, {__tostring=function (o)
|
|
+ assert(o == x)
|
|
+ return "ABC"
|
|
+ end})
|
|
+ a, b, c = T.testC("pushint 10; Ltolstring -2; return 3", x)
|
|
+ assert(a == x and b == 10 and c == "ABC")
|
|
+ end
|
|
end
|
|
|
|
-- global functions
|
|
diff --git a/ltests.c b/ltests.c
|
|
index a50f78304..97834e380 100644
|
|
--- a/ltests/ltests.c
|
|
+++ b/ltests/ltests.c
|
|
@@ -1743,6 +1743,9 @@ static struct X { int x; } x;
|
|
(void)s1; /* to avoid warnings */
|
|
lua_longassert((s == NULL && s1 == NULL) || strcmp(s, s1) == 0);
|
|
}
|
|
+ else if EQ("Ltolstring") {
|
|
+ luaL_tolstring(L1, getindex, NULL);
|
|
+ }
|
|
else if EQ("type") {
|
|
lua_pushstring(L1, luaL_typename(L1, getnum));
|
|
}
|
|
diff --git a/testes/cstack.lua b/testes/cstack.lua
|
|
index 213d15d47..ca76c8729 100644
|
|
--- a/cstack.lua
|
|
+++ b/cstack.lua
|
|
@@ -103,6 +103,20 @@ do
|
|
end
|
|
|
|
|
|
+do -- bug in 5.4.2
|
|
+ print("nesting coroutines running after recoverable errors")
|
|
+ local count = 0
|
|
+ local function foo()
|
|
+ count = count + 1
|
|
+ pcall(1) -- create an error
|
|
+ -- running now inside 'precover' ("protected recover")
|
|
+ coroutine.wrap(foo)() -- call another coroutine
|
|
+ end
|
|
+ checkerror("C stack overflow", foo)
|
|
+ print("final count: ", count)
|
|
+end
|
|
+
|
|
+
|
|
if T then
|
|
print("testing stack recovery")
|
|
local N = 0 -- trace number of calls
|
|
diff --git a/testes/coroutine.lua b/testes/coroutine.lua
|
|
index 461e03770..76c9d6e63 100644
|
|
--- a/coroutine.lua
|
|
+++ b/coroutine.lua
|
|
@@ -136,6 +136,10 @@ do
|
|
assert(coroutine.status(co) == "dead")
|
|
local st, msg = coroutine.close(co)
|
|
assert(st and msg == nil)
|
|
+ -- also ok to close it again
|
|
+ st, msg = coroutine.close(co)
|
|
+ assert(st and msg == nil)
|
|
+
|
|
|
|
-- cannot close the running coroutine
|
|
local st, msg = pcall(coroutine.close, coroutine.running())
|
|
@@ -149,6 +153,22 @@ do
|
|
assert(not st and string.find(msg, "normal"))
|
|
end))()
|
|
|
|
+ -- cannot close a coroutine while closing it
|
|
+ do
|
|
+ local co
|
|
+ co = coroutine.create(
|
|
+ function()
|
|
+ local x <close> = func2close(function()
|
|
+ coroutine.close(co) -- try to close it again
|
|
+ end)
|
|
+ coroutine.yield(20)
|
|
+ end)
|
|
+ local st, msg = coroutine.resume(co)
|
|
+ assert(st and msg == 20)
|
|
+ st, msg = coroutine.close(co)
|
|
+ assert(not st and string.find(msg, "running coroutine"))
|
|
+ end
|
|
+
|
|
-- to-be-closed variables in coroutines
|
|
local X
|
|
|
|
@@ -158,6 +178,9 @@ do
|
|
assert(not st and msg == 100)
|
|
st, msg = coroutine.close(co)
|
|
assert(not st and msg == 100)
|
|
+ -- after closing, no more errors
|
|
+ st, msg = coroutine.close(co)
|
|
+ assert(st and msg == nil)
|
|
|
|
co = coroutine.create(function ()
|
|
local x <close> = func2close(function (self, err)
|
|
@@ -189,6 +212,9 @@ do
|
|
local st, msg = coroutine.close(co)
|
|
assert(st == false and coroutine.status(co) == "dead" and msg == 200)
|
|
assert(x == 200)
|
|
+ -- after closing, no more errors
|
|
+ st, msg = coroutine.close(co)
|
|
+ assert(st and msg == nil)
|
|
end
|
|
|
|
do
|
|
@@ -419,7 +445,7 @@ do
|
|
|
|
local X = false
|
|
A = coroutine.wrap(function()
|
|
- local _ <close> = setmetatable({}, {__close = function () X = true end})
|
|
+ local _ <close> = func2close(function () X = true end)
|
|
return pcall(A, 1)
|
|
end)
|
|
st, res = A()
|
|
@@ -427,6 +453,22 @@ do
|
|
end
|
|
|
|
|
|
+-- bug in 5.4.1
|
|
+do
|
|
+ -- coroutine ran close metamethods with invalid status during a
|
|
+ -- reset.
|
|
+ local co
|
|
+ co = coroutine.wrap(function()
|
|
+ local x <close> = func2close(function() return pcall(co) end)
|
|
+ error(111)
|
|
+ end)
|
|
+ local st, errobj = pcall(co)
|
|
+ assert(not st and errobj == 111)
|
|
+ st, errobj = pcall(co)
|
|
+ assert(not st and string.find(errobj, "dead coroutine"))
|
|
+end
|
|
+
|
|
+
|
|
-- attempt to resume 'normal' coroutine
|
|
local co1, co2
|
|
co1 = coroutine.create(function () return co2() end)
|
|
diff --git a/testes/api.lua b/testes/api.lua
|
|
index c1bcb4b7b..bd85a923c 100644
|
|
--- a/api.lua
|
|
+++ b/api.lua
|
|
@@ -804,15 +804,14 @@ F = function (x)
|
|
d = nil
|
|
assert(debug.getmetatable(x).__gc == F)
|
|
assert(load("table.insert({}, {})"))() -- create more garbage
|
|
- collectgarbage() -- force a GC during GC
|
|
- assert(debug.getmetatable(x).__gc == F) -- previous GC did not mess this?
|
|
+ assert(not collectgarbage()) -- GC during GC (no op)
|
|
local dummy = {} -- create more garbage during GC
|
|
if A ~= nil then
|
|
assert(type(A) == "userdata")
|
|
assert(T.udataval(A) == B)
|
|
debug.getmetatable(A) -- just access it
|
|
end
|
|
- A = x -- ressucita userdata
|
|
+ A = x -- ressurect userdata
|
|
B = udval
|
|
return 1,2,3
|
|
end
|
|
diff --git a/testes/gc.lua b/testes/gc.lua
|
|
index 2332c939a..d865cb28d 100644
|
|
--- a/gc.lua
|
|
+++ b/gc.lua
|
|
@@ -676,11 +676,13 @@ end
|
|
-- just to make sure
|
|
assert(collectgarbage'isrunning')
|
|
|
|
-do -- check that the collector is reentrant in incremental mode
|
|
+do -- check that the collector is not reentrant in incremental mode
|
|
+ local res = true
|
|
setmetatable({}, {__gc = function ()
|
|
- collectgarbage()
|
|
+ res = collectgarbage()
|
|
end})
|
|
collectgarbage()
|
|
+ assert(not res)
|
|
end
|
|
|
|
|
|
diff --git a/testes/main.lua b/testes/main.lua
|
|
index 52c779541..9def63860 100644
|
|
--- a/main.lua
|
|
+++ b/main.lua
|
|
@@ -261,6 +261,34 @@ u2 = setmetatable({}, {__gc = function () error("ZYX") end})
|
|
RUN('lua -W %s 2> %s', prog, out)
|
|
checkprogout("ZYX)\nXYZ)\n")
|
|
|
|
+-- bug since 5.2: finalizer called when closing a state could
|
|
+-- subvert finalization order
|
|
+prepfile[[
|
|
+-- should be called last
|
|
+print("creating 1")
|
|
+setmetatable({}, {__gc = function () print(1) end})
|
|
+
|
|
+print("creating 2")
|
|
+setmetatable({}, {__gc = function ()
|
|
+ print("2")
|
|
+ print("creating 3")
|
|
+ -- this finalizer should not be called, as object will be
|
|
+ -- created after 'lua_close' has been called
|
|
+ setmetatable({}, {__gc = function () print(3) end})
|
|
+ print(collectgarbage()) -- cannot call collector here
|
|
+ os.exit(0, true)
|
|
+end})
|
|
+]]
|
|
+RUN('lua -W %s > %s', prog, out)
|
|
+checkout[[
|
|
+creating 1
|
|
+creating 2
|
|
+2
|
|
+creating 3
|
|
+nil
|
|
+1
|
|
+]]
|
|
+
|
|
|
|
-- test many arguments
|
|
prepfile[[print(({...})[30])]]
|