Hello community,

here is the log from the commit of package lua54 for openSUSE:Factory checked 
in at 2020-10-12 13:46:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/lua54 (Old)
 and      /work/SRC/openSUSE:Factory/.lua54.new.3486 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "lua54"

Mon Oct 12 13:46:38 2020 rev:5 rq:840777 version:5.4.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/lua54/lua54.changes      2020-08-28 
23:44:51.903506140 +0200
+++ /work/SRC/openSUSE:Factory/.lua54.new.3486/lua54.changes    2020-10-12 
13:46:52.197910487 +0200
@@ -1,0 +2,7 @@
+Sat Oct 10 13:10:50 UTC 2020 - Callum Farmer <callumjfarme...@gmail.com>
+
+- Update to version 5.4.1:
+  * Fixes bugs found in Lua 5.4.0
+- Removed upstream-bugs.patch: new release (no bugs found yet)
+
+-------------------------------------------------------------------

Old:
----
  lua-5.4.0-tests.tar.gz
  lua-5.4.0.tar.gz
  upstream-bugs.patch

New:
----
  lua-5.4.1-tests.tar.gz
  lua-5.4.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ lua54.spec ++++++
--- /var/tmp/diff_new_pack.smUT5o/_old  2020-10-12 13:46:52.905910775 +0200
+++ /var/tmp/diff_new_pack.smUT5o/_new  2020-10-12 13:46:52.909910776 +0200
@@ -19,14 +19,14 @@
 %define major_version 5.4
 %define libname liblua5_4-5
 Name:           lua54
-Version:        5.4.0
+Version:        5.4.1
 Release:        0
 Summary:        Small Embeddable Language with Procedural Syntax
 License:        MIT
 Group:          Development/Languages/Other
 URL:            http://www.lua.org
-Source:         http://www.lua.org/ftp/lua-5.4.0.tar.gz
-Source1:        http://www.lua.org/tests/lua-5.4.0-tests.tar.gz
+Source:         http://www.lua.org/ftp/lua-%{version}.tar.gz
+Source1:        http://www.lua.org/tests/lua-%{version}-tests.tar.gz
 Source99:       baselibs.conf
 # PATCH-FIX-SUSE tweak the buildsystem to produce what is needed for SUSE
 Patch0:         lua-build-system.patch
@@ -34,8 +34,8 @@
 # Fix failing test
 Patch1:         attrib_test.patch
 Patch2:         files_test.patch
-# PATCH-FIX-UPSTREAM https://www.lua.org/bugs.html
-Patch3:         upstream-bugs.patch
+# PATCH-FIX-UPSTREAM https://www.lua.org/bugs.html#5.4.1
+#Patch3:         upstream-bugs.patch
 BuildRequires:  libtool
 BuildRequires:  lua-macros
 BuildRequires:  pkgconfig

++++++ attrib_test.patch ++++++
--- /var/tmp/diff_new_pack.smUT5o/_old  2020-10-12 13:46:52.937910788 +0200
+++ /var/tmp/diff_new_pack.smUT5o/_new  2020-10-12 13:46:52.937910788 +0200
@@ -1,5 +1,5 @@
---- a/lua-5.4.0-tests/attrib.lua
-+++ b/lua-5.4.0-tests/attrib.lua
+--- a/lua-5.4.1-tests/attrib.lua
++++ b/lua-5.4.1-tests/attrib.lua
 @@ -269,7 +269,7 @@ local p = ""   -- On Mac OS X, redefine
  local st, err, when = package.loadlib(DC"lib1", "*")
  if not st then

++++++ files_test.patch ++++++
--- /var/tmp/diff_new_pack.smUT5o/_old  2020-10-12 13:46:52.961910798 +0200
+++ /var/tmp/diff_new_pack.smUT5o/_new  2020-10-12 13:46:52.965910799 +0200
@@ -1,7 +1,7 @@
-Index: lua-5.4.0/lua-5.4.0-tests/files.lua
+Index: lua-5.4.1/lua-5.4.1-tests/files.lua
 ===================================================================
---- lua-5.4.0.orig/lua-5.4.0-tests/files.lua
-+++ lua-5.4.0/lua-5.4.0-tests/files.lua
+--- lua-5.4.1.orig/lua-5.4.1-tests/files.lua
++++ lua-5.4.1/lua-5.4.1-tests/files.lua
 @@ -81,7 +81,7 @@ assert(io.output() ~= io.stdout)
  
  if not _port then   -- invalid seek

++++++ lua-5.4.0-tests.tar.gz -> lua-5.4.1-tests.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/api.lua new/lua-5.4.1-tests/api.lua
--- old/lua-5.4.0-tests/api.lua 2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/api.lua 2020-09-30 11:36:52.000000000 +0200
@@ -11,6 +11,9 @@
 local pack = table.pack
 
 
+-- standard error message for memory errors
+local MEMERRMSG = "not enough memory"
+
 function tcheck (t1, t2)
   assert(t1.n == (t2.n or #t2) + 1)
   for i = 2, t1.n do assert(t1[i] == t2[i - 1]) end
@@ -408,7 +411,7 @@
 
   -- memory error
   T.totalmem(T.totalmem()+10000)   -- set low memory limit (+10k)
-  assert(T.checkpanic("newuserdata 20000") == "not enough memory")
+  assert(T.checkpanic("newuserdata 20000") == MEMERRMSG)
   T.totalmem(0)          -- restore high limit
 
   -- stack error
@@ -1153,40 +1156,74 @@
 end
 
 
--------------------------------------------------------------------------
--- testing memory limits
--------------------------------------------------------------------------
+--[[
+** {==================================================================
+** Testing memory limits
+** ===================================================================
+--]]
+
 print("memory-allocation errors")
 
 checkerr("block too big", T.newuserdata, math.maxinteger)
 collectgarbage()
 local f = load"local a={}; for i=1,100000 do a[i]=i end"
 T.alloccount(10)
-checkerr("not enough memory", f)
+checkerr(MEMERRMSG, f)
 T.alloccount()          -- remove limit
 
+
+-- test memory errors; increase limit for maximum memory by steps,
+-- o that we get memory errors in all allocations of a given
+-- task, until there is enough memory to complete the task without
+-- errors.
+function testbytes (s, f)
+  collectgarbage()
+  local M = T.totalmem()
+  local oldM = M
+  local a,b = nil
+  while true do
+    collectgarbage(); collectgarbage()
+    T.totalmem(M)
+    a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
+    T.totalmem(0)  -- remove limit
+    if a and b == "OK" then break end       -- stop when no more errors
+    if b ~= "OK" and b ~= MEMERRMSG then    -- not a memory error?
+      error(a, 0)   -- propagate it
+    end
+    M = M + 7   -- increase memory limit
+  end
+  print(string.format("minimum memory for %s: %d bytes", s, M - oldM))
+  return a
+end
+
 -- test memory errors; increase limit for number of allocations one
 -- by one, so that we get memory errors in all allocations of a given
 -- task, until there is enough allocations to complete the task without
 -- errors.
 
-function testamem (s, f)
-  collectgarbage(); collectgarbage()
+function testalloc (s, f)
+  collectgarbage()
   local M = 0
   local a,b = nil
   while true do
+    collectgarbage(); collectgarbage()
     T.alloccount(M)
-    a, b = pcall(f)
+    a, b = T.testC("pcall 0 1 0; pushstatus; return 2", f)
     T.alloccount()  -- remove limit
-    if a and b then break end       -- stop when no more errors
-    if not a and not    -- `real' error?
-      (string.find(b, "memory") or string.find(b, "overflow")) then
-      error(b, 0)   -- propagate it
+    if a and b == "OK" then break end       -- stop when no more errors
+    if b ~= "OK" and b ~= MEMERRMSG then    -- not a memory error?
+      error(a, 0)   -- propagate it
     end
     M = M + 1   -- increase allocation limit
   end
-  print(string.format("limit for %s: %d allocations", s, M))
-  return b
+  print(string.format("minimum allocations for %s: %d allocations", s, M))
+  return a
+end
+
+
+local function testamem (s, f)
+  testalloc(s, f)
+  return testbytes(s, f)
 end
 
 
@@ -1196,8 +1233,11 @@
 
 -- testing memory errors when creating a new state
 
-b = testamem("state creation", T.newstate)
-T.closestate(b);  -- close new state
+testamem("state creation", function ()
+  local st = T.newstate()
+  if st then T.closestate(st) end   -- close new state
+  return st
+end)
 
 testamem("empty-table creation", function ()
   return {}
@@ -1345,6 +1385,9 @@
   return foo(100)
 end)
 
+-- }==================================================================
+
+
 do   -- testing failing in 'lua_checkstack'
   local res = T.testC([[rawcheckstack 500000; return 1]])
   assert(res == false)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/calls.lua 
new/lua-5.4.1-tests/calls.lua
--- old/lua-5.4.0-tests/calls.lua       2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/calls.lua       2020-09-30 11:36:53.000000000 +0200
@@ -317,6 +317,16 @@
 assert(type(f) == "function" and f() == 1)
 
 
+do   -- another bug (in 5.4.0)
+  -- loading a binary long string interrupted by GC cycles
+  local f = string.dump(function ()
+    return '01234567890123456789012345678901234567890123456789'
+  end)
+  f = load(read1(f))
+  assert(f() == '01234567890123456789012345678901234567890123456789')
+end
+
+
 x = string.dump(load("x = 1; return x"))
 a = assert(load(read1(x), nil, "b"))
 assert(a() == 1 and _G.x == 1)
@@ -358,8 +368,12 @@
    end
   end
 ]]
+a = assert(load(read1(x), "read", "t"))
+assert(a()(2)(3)(10) == 15)
 
-a = assert(load(read1(x)))
+-- repeat the test loading a binary chunk
+x = string.dump(a)
+a = assert(load(read1(x), "read", "b"))
 assert(a()(2)(3)(10) == 15)
 
 
@@ -422,20 +436,30 @@
 
 print("testing binary chunks")
 do
-  local header = string.pack("c4BBc6BBBj",
+  local header = string.pack("c4BBc6BBB",
     "\27Lua",                                  -- signature
     0x54,                                      -- version 5.4 (0x54)
     0,                                         -- format
     "\x19\x93\r\n\x1a\n",                      -- data
     4,                                         -- size of instruction
     string.packsize("j"),                      -- sizeof(lua integer)
-    string.packsize("n"),                      -- sizeof(lua number)
-    0x5678                                     -- LUAC_INT
-    -- LUAC_NUM may not have a unique binary representation (padding...)
+    string.packsize("n")                       -- sizeof(lua number)
   )
-  local c = string.dump(function () local a = 1; local b = 3; return a+b*3 end)
+  local c = string.dump(function ()
+    local a = 1; local b = 3;
+    local f = function () return a + b + _ENV.c; end    -- upvalues
+    local s1 = "a constant"
+    local s2 = "another constant"
+    return a + b * 3
+  end)
 
+  assert(assert(load(c))() == 10)
+
+  -- check header
   assert(string.sub(c, 1, #header) == header)
+  -- check LUAC_INT and LUAC_NUM
+  local ci, cn = string.unpack("jn", c, #header + 1)
+  assert(ci == 0x5678 and cn == 370.5)
 
   -- corrupted header
   for i = 1, #header do
@@ -451,7 +475,6 @@
     local st, msg = load(string.sub(c, 1, i))
     assert(not st and string.find(msg, "truncated"))
   end
-  assert(assert(load(c))() == 10)
 end
 
 print('OK')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/coroutine.lua 
new/lua-5.4.1-tests/coroutine.lua
--- old/lua-5.4.0-tests/coroutine.lua   2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/coroutine.lua   2020-09-30 11:36:53.000000000 +0200
@@ -184,7 +184,7 @@
   if not T then
     warn("@on")
   else   -- test library
-    assert(string.find(_WARN, "200")); _WARN = nil
+    assert(string.find(_WARN, "200")); _WARN = false
     warn("@normal")
   end
   assert(st == false and coroutine.status(co) == "dead" and msg == 111)
@@ -407,7 +407,8 @@
 
 
 if not T then
-  (Message or print)('\n >>> testC not active: skipping yield/hook tests 
<<<\n')
+  (Message or print)
+      ('\n >>> testC not active: skipping coroutine API tests <<<\n')
 else
   print "testing yields inside hooks"
 
@@ -564,8 +565,17 @@
          c == "ERRRUN" and d == 4)
 
 
-  -- using a main thread as a coroutine
+  -- using a main thread as a coroutine  (dubious use!)
   local state = T.newstate()
+
+  -- check that yielddable is working correctly
+  assert(T.testC(state, "newthread; isyieldable -1; remove 1; return 1"))
+
+  -- main thread is not yieldable
+  assert(not T.testC(state, "rawgeti R 1; isyieldable -1; remove 1; return 1"))
+
+  T.testC(state, "settop 0")
+
   T.loadlib(state)
 
   assert(T.doremote(state, [[
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/cstack.lua 
new/lua-5.4.1-tests/cstack.lua
--- old/lua-5.4.0-tests/cstack.lua      2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/cstack.lua      2020-09-30 11:36:53.000000000 +0200
@@ -105,6 +105,22 @@
   print("\tfinal count: ", count)
 end
 
+do   -- bug in 5.4.0
+  print("testing limits in coroutines inside deep calls")
+  count = 0
+  local lim = 1000
+  local function stack (n)
+    progress()
+    if n > 0 then return stack(n - 1) + 1
+    else coroutine.wrap(function ()
+           stack(lim)
+         end)()
+    end
+  end
+
+  print(xpcall(stack, function () return "ok" end, lim))
+end
+
 
 do  print("testing changes in C-stack limit")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/db.lua new/lua-5.4.1-tests/db.lua
--- old/lua-5.4.0-tests/db.lua  2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/db.lua  2020-09-30 11:36:53.000000000 +0200
@@ -884,7 +884,7 @@
 
 
 print("testing debug functions on chunk without debug info")
-prog = [[-- program to be loaded without debug information
+prog = [[-- program to be loaded without debug information (strip)
 local debug = require'debug'
 local a = 12  -- a local variable
 
@@ -927,6 +927,23 @@
 
 assert(f() == 13)
 
+do   -- bug in 5.4.0: line hooks in stripped code
+  local function foo ()
+    local a = 1
+    local b = 2
+    return b
+  end
+
+  local s = load(string.dump(foo, true))
+  local line = true
+  debug.sethook(function (e, l)
+    assert(e == "line")
+    line = l
+  end, "l")
+  assert(s() == 2); debug.sethook(nil)
+  assert(line == nil)  -- hook called withoug debug info for 1st instruction
+end
+
 do   -- tests for 'source' in binary dumps
   local prog = [[
     return function (x)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/events.lua 
new/lua-5.4.1-tests/events.lua
--- old/lua-5.4.0-tests/events.lua      2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/events.lua      2020-09-30 11:36:53.000000000 +0200
@@ -305,6 +305,17 @@
 assert(t[Set{1,3,5}] == undef)
 
 
+do   -- test invalidating flags
+  local mt = {__eq = true}
+  local a = setmetatable({10}, mt)
+  local b = setmetatable({10}, mt)
+  mt.__eq = nil
+  assert(a ~= b)   -- no metamethod
+  mt.__eq = function (x,y) return x[1] == y[1] end
+  assert(a == b)   -- must use metamethod now
+end
+
+
 if not T then
   (Message or print)('\n >>> testC not active: skipping tests for \z
 userdata <<<\n')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/files.lua 
new/lua-5.4.1-tests/files.lua
--- old/lua-5.4.0-tests/files.lua       2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/files.lua       2020-09-30 11:36:53.000000000 +0200
@@ -721,6 +721,21 @@
     progname = '"' .. arg[i + 1] .. '"'
   end
   print("testing popen/pclose and execute")
+  -- invalid mode for popen
+  checkerr("invalid mode", io.popen, "cat", "")
+  checkerr("invalid mode", io.popen, "cat", "r+")
+  checkerr("invalid mode", io.popen, "cat", "rw")
+  do  -- basic tests for popen
+    local file = os.tmpname()
+    local f = assert(io.popen("cat - > " .. file, "w"))
+    f:write("a line")
+    assert(f:close())
+    local f = assert(io.popen("cat - < " .. file, "r"))
+    assert(f:read("a") == "a line")
+    assert(f:close())
+    assert(os.remove(file))
+  end
+
   local tests = {
     -- command,   what,  code
     {"ls > /dev/null", "ok"},
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/gc.lua new/lua-5.4.1-tests/gc.lua
--- old/lua-5.4.0-tests/gc.lua  2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/gc.lua  2020-09-30 11:36:53.000000000 +0200
@@ -372,7 +372,7 @@
   warn("@on"); warn("@store")
   collectgarbage()
   assert(string.find(_WARN, "error in __gc metamethod"))
-  assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = nil
+  assert(string.match(_WARN, "@(.-)@") == "expected"); _WARN = false
   for i = 8, 10 do assert(s[i]) end
 
   for i = 1, 5 do
@@ -481,7 +481,7 @@
   u = setmetatable({}, {__gc = function () error "@expected error" end})
   u = nil
   collectgarbage()
-  assert(string.find(_WARN, "@expected error")); _WARN = nil
+  assert(string.find(_WARN, "@expected error")); _WARN = false
   warn("@normal")
 end
 
@@ -657,14 +657,14 @@
     n = n + 1
     assert(n == o[1])
     if n == 1 then
-      _WARN = nil
+      _WARN = false
     elseif n == 2 then
       assert(find(_WARN, "@expected warning"))
       lastmsg = _WARN    -- get message from previous error (first 'o')
     else
       assert(lastmsg == _WARN)  -- subsequent error messages are equal
     end
-    warn("@store"); _WARN = nil
+    warn("@store"); _WARN = false
     error"@expected warning"
   end}
   for i = 10, 1, -1 do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/gengc.lua 
new/lua-5.4.1-tests/gengc.lua
--- old/lua-5.4.0-tests/gengc.lua       2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/gengc.lua       2020-09-30 11:36:53.000000000 +0200
@@ -37,6 +37,92 @@
 end
 
 
+do
+  -- ensure that 'firstold1' is corrected when object is removed from
+  -- the 'allgc' list
+  local function foo () end
+  local old = {10}
+  collectgarbage()    -- make 'old' old
+  assert(not T or T.gcage(old) == "old")
+  setmetatable(old, {})    -- new table becomes OLD0 (barrier)
+  assert(not T or T.gcage(getmetatable(old)) == "old0")
+  collectgarbage("step", 0)   -- new table becomes OLD1 and firstold1
+  assert(not T or T.gcage(getmetatable(old)) == "old1")
+  setmetatable(getmetatable(old), {__gc = foo})  -- get it out of allgc list
+  collectgarbage("step", 0)   -- should not seg. fault
+end
+
+
+do   -- bug in 5.4.0
+-- When an object aged OLD1 is finalized, it is moved from the list
+-- 'finobj' to the *beginning* of the list 'allgc', but that part of the
+-- list was not being visited by 'markold'.
+  local A = {}
+  A[1] = false     -- old anchor for object
+
+  -- obj finalizer
+  local function gcf (obj)
+    A[1] = obj     -- anchor object
+    assert(not T or T.gcage(obj) == "old1")
+    obj = nil      -- remove it from the stack
+    collectgarbage("step", 0)   -- do a young collection
+    print(getmetatable(A[1]).x)   -- metatable was collected
+  end
+
+  collectgarbage()   -- make A old
+  local obj = {}     -- create a new object
+  collectgarbage("step", 0)   -- make it a survival
+  assert(not T or T.gcage(obj) == "survival")
+  setmetatable(obj, {__gc = gcf, x = "+"})   -- create its metatable
+  assert(not T or T.gcage(getmetatable(obj)) == "new")
+  obj = nil   -- clear object
+  collectgarbage("step", 0)   -- will call obj's finalizer
+end
+
+
+do   -- another bug in 5.4.0
+  local old = {10}
+  collectgarbage()   -- make 'old' old
+  local co = coroutine.create(
+    function ()
+      local x = nil
+      local f = function ()
+                  return x[1]
+                end
+      x = coroutine.yield(f)
+      coroutine.yield()
+    end
+  )
+  local _, f = coroutine.resume(co)   -- create closure over 'x' in coroutine
+  collectgarbage("step", 0)   -- make upvalue a survival
+  old[1] = {"hello"}    -- 'old' go to grayagain as 'touched1'
+  coroutine.resume(co, {123})     -- its value will be new
+  co = nil
+  collectgarbage("step", 0)   -- hit the barrier
+  assert(f() == 123 and old[1][1] == "hello")
+  collectgarbage("step", 0)   -- run the collector once more
+  -- make sure old[1] was not collected
+  assert(f() == 123 and old[1][1] == "hello")
+end
+
+
+do   -- bug introduced in commit 9cf3299fa
+  local t = setmetatable({}, {__mode = "kv"})   -- all-weak table
+  collectgarbage()   -- full collection
+  assert(not T or T.gcage(t) == "old")
+  t[1] = {10}
+  assert(not T or (T.gcage(t) == "touched1" and T.gccolor(t) == "gray"))
+  collectgarbage("step", 0)   -- minor collection
+  assert(not T or (T.gcage(t) == "touched2" and T.gccolor(t) == "black"))
+  collectgarbage("step", 0)   -- minor collection
+  assert(not T or T.gcage(t) == "old")   -- t should be black, but it was gray
+  t[1] = {10}      -- no barrier here, so t was still old
+  collectgarbage("step", 0)   -- minor collection
+  -- t, being old, is ignored by the collection, so it is not cleared
+  assert(t[1] == nil)   -- fails with the bug
+end
+
+
 if T == nil then
   (Message or print)('\n >>> testC not active: \z
                              skipping some generational tests <<<\n')
@@ -72,6 +158,9 @@
   assert(debug.getuservalue(U).x[1] == 234)
 end
 
+-- just to make sure
+assert(collectgarbage'isrunning')
+
 
 
 -- just to make sure
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/locals.lua 
new/lua-5.4.1-tests/locals.lua
--- old/lua-5.4.0-tests/locals.lua      2020-06-18 16:25:55.000000000 +0200
+++ new/lua-5.4.1-tests/locals.lua      2020-09-30 11:36:54.000000000 +0200
@@ -337,7 +337,7 @@
   if not T then
     warn("@on")          -- back to normal
   else
-    assert(_WARN == nil)
+    assert(_WARN == false)
     warn("@normal")
   end
 end
@@ -346,7 +346,7 @@
 local function checkwarn (msg)
   if T then
     assert(string.find(_WARN, msg))
-    _WARN = nil    -- reset variable to check next warning
+    _WARN = false    -- reset variable to check next warning
   end
 end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/ltests/ltests.c 
new/lua-5.4.1-tests/ltests/ltests.c
--- old/lua-5.4.0-tests/ltests/ltests.c 2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/ltests/ltests.c 2020-09-30 11:36:51.000000000 +0200
@@ -121,7 +121,8 @@
   strcat(buff, msg);  /* add new message to current warning */
   if (!tocont) {  /* message finished? */
     lua_unlock(L);
-    if (lua_getglobal(L, "_WARN") == LUA_TNIL)
+    lua_getglobal(L, "_WARN");
+    if (!lua_toboolean(L, -1))
       lua_pop(L, 1);  /* ok, no previous unexpected warning */
     else {
       badexit("Unhandled warning in store mode: %s\naborting...\n",
@@ -144,7 +145,6 @@
         lua_pushstring(L, buff);
         lua_setglobal(L, "_WARN");  /* assign message to global '_WARN' */
         lua_lock(L);
-        buff[0] = '\0';  /* prepare buffer for next warning */
         break;
       }
     }
@@ -186,7 +186,8 @@
 
 
 Memcontrol l_memcontrol =
-  {0UL, 0UL, 0UL, 0UL, (~0UL), {0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}};
+  {0, 0UL, 0UL, 0UL, 0UL, (~0UL),
+   {0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL}};
 
 
 static void freeblock (Memcontrol *mc, Header *block) {
@@ -225,6 +226,10 @@
     freeblock(mc, block);
     return NULL;
   }
+  if (mc->failnext) {
+    mc->failnext = 0;
+    return NULL;  /* fake a single memory allocation error */
+  }
   if (mc->countlimit != ~0UL && size != oldsize) {  /* count limit in use? */
     if (mc->countlimit == 0)
       return NULL;  /* fake a memory allocation error */
@@ -309,6 +314,10 @@
 }
 
 
+void lua_printobj (lua_State *L, struct GCObject *o) {
+  printobj(G(L), o);
+}
+
 static int testobjref (global_State *g, GCObject *f, GCObject *t) {
   int r1 = testobjref1(g, f, t);
   if (!r1) {
@@ -509,10 +518,16 @@
 }
 
 
-static void checkgraylist (global_State *g, GCObject *o) {
+static lu_mem checkgraylist (global_State *g, GCObject *o) {
+  int total = 0;  /* count number of elements in the list */
   ((void)g);  /* better to keep it available if we need to print an object */
   while (o) {
-    lua_assert(isgray(o) || getage(o) == G_TOUCHED2);
+    lua_assert(!!isgray(o) ^ (getage(o) == G_TOUCHED2));
+    //lua_assert(isgray(o) || getage(o) == G_TOUCHED2);
+    lua_assert(!testbit(o->marked, TESTBIT));
+    if (keepinvariant(g))
+      l_setbit(o->marked, TESTBIT);  /* mark that object is in a gray list */
+    total++;
     switch (o->tt) {
       case LUA_VTABLE: o = gco2t(o)->gclist; break;
       case LUA_VLCL: o = gco2lcl(o)->gclist; break;
@@ -526,40 +541,72 @@
       default: lua_assert(0);  /* other objects cannot be in a gray list */
     }
   }
+  return total;
 }
 
 
 /*
 ** Check objects in gray lists.
 */
-static void checkgrays (global_State *g) {
-  if (!keepinvariant(g)) return;
-  checkgraylist(g, g->gray);
-  checkgraylist(g, g->grayagain);
-  checkgraylist(g, g->weak);
-  checkgraylist(g, g->ephemeron);
+static lu_mem checkgrays (global_State *g) {
+  int total = 0;  /* count number of elements in all lists */
+  if (!keepinvariant(g)) return total;
+  total += checkgraylist(g, g->gray);
+  total += checkgraylist(g, g->grayagain);
+  total += checkgraylist(g, g->weak);
+  total += checkgraylist(g, g->allweak);
+  total += checkgraylist(g, g->ephemeron);
+  return total;
 }
 
 
-static void checklist (global_State *g, int maybedead, int tof,
+/*
+** Check whether 'o' should be in a gray list. If so, increment
+** 'count' and check its TESTBIT. (It must have been previously set by
+** 'checkgraylist'.)
+*/
+static void incifingray (global_State *g, GCObject *o, lu_mem *count) {
+  if (!keepinvariant(g))
+    return;  /* gray lists not being kept in these phases */
+  if (o->tt == LUA_VUPVAL) {
+    /* only open upvalues can be gray */
+    lua_assert(!isgray(o) || upisopen(gco2upv(o)));
+    return;  /* upvalues are never in gray lists */
+  }
+  /* these are the ones that must be in gray lists */
+  if (isgray(o) || getage(o) == G_TOUCHED2) {
+    (*count)++;
+    lua_assert(testbit(o->marked, TESTBIT));
+    resetbit(o->marked, TESTBIT);  /* prepare for next cycle */
+  }
+}
+
+
+static lu_mem checklist (global_State *g, int maybedead, int tof,
   GCObject *newl, GCObject *survival, GCObject *old, GCObject *reallyold) {
   GCObject *o;
+  lu_mem total = 0;  /* number of object that should be in  gray lists */
   for (o = newl; o != survival; o = o->next) {
     checkobject(g, o, maybedead, G_NEW);
+    incifingray(g, o, &total);
     lua_assert(!tof == !tofinalize(o));
   }
   for (o = survival; o != old; o = o->next) {
     checkobject(g, o, 0, G_SURVIVAL);
+    incifingray(g, o, &total);
     lua_assert(!tof == !tofinalize(o));
   }
   for (o = old; o != reallyold; o = o->next) {
     checkobject(g, o, 0, G_OLD1);
+    incifingray(g, o, &total);
     lua_assert(!tof == !tofinalize(o));
   }
   for (o = reallyold; o != NULL; o = o->next) {
     checkobject(g, o, 0, G_OLD);
+    incifingray(g, o, &total);
     lua_assert(!tof == !tofinalize(o));
   }
+  return total;
 }
 
 
@@ -567,13 +614,15 @@
   global_State *g = G(L);
   GCObject *o;
   int maybedead;
+  lu_mem totalin;  /* total of objects that are in gray lists */
+  lu_mem totalshould;  /* total of objects that should be in gray lists */
   if (keepinvariant(g)) {
     lua_assert(!iswhite(g->mainthread));
     lua_assert(!iswhite(gcvalue(&g->l_registry)));
   }
   lua_assert(!isdead(g, gcvalue(&g->l_registry)));
   lua_assert(g->sweepgc == NULL || issweepphase(g));
-  checkgrays(g);
+  totalin = checkgrays(g);
 
   /* check 'fixedgc' list */
   for (o = g->fixedgc; o != NULL; o = o->next) {
@@ -582,17 +631,22 @@
 
   /* check 'allgc' list */
   maybedead = (GCSatomic < g->gcstate && g->gcstate <= GCSswpallgc);
-  checklist(g, maybedead, 0, g->allgc, g->survival, g->old, g->reallyold);
+  totalshould = checklist(g, maybedead, 0, g->allgc,
+                             g->survival, g->old1, g->reallyold);
 
   /* check 'finobj' list */
-  checklist(g, 0, 1, g->finobj, g->finobjsur, g->finobjold, g->finobjrold);
+  totalshould += checklist(g, 0, 1, g->finobj,
+                              g->finobjsur, g->finobjold1, g->finobjrold);
 
   /* check 'tobefnz' list */
   for (o = g->tobefnz; o != NULL; o = o->next) {
     checkobject(g, o, 0, G_NEW);
+    incifingray(g, o, &totalshould);
     lua_assert(tofinalize(o));
     lua_assert(o->tt == LUA_VUSERDATA || o->tt == LUA_VTABLE);
   }
+  if (keepinvariant(g))
+    lua_assert(totalin == totalshould);
   return 0;
 }
 
@@ -748,11 +802,12 @@
 static void printstack (lua_State *L) {
   int i;
   int n = lua_gettop(L);
+  printf("stack: >>\n");
   for (i = 1; i <= n; i++) {
     printf("%3d: %s\n", i, luaL_tolstring(L, i, NULL));
     lua_pop(L, 1);
   }
-  printf("\n");
+  printf("<<\n");
 }
 
 
@@ -802,6 +857,13 @@
     l_memcontrol.countlimit = luaL_checkinteger(L, 1);
   return 0;
 }
+
+
+static int alloc_failnext (lua_State *L) {
+  UNUSED(L);
+  l_memcontrol.failnext = 1;
+  return 0;
+}
   
 
 static int settrick (lua_State *L) {
@@ -1282,10 +1344,19 @@
 }
 
 
-static void pushcode (lua_State *L, int code) {
-  static const char *const codes[] = {"OK", "YIELD", "ERRRUN",
-                   "ERRSYNTAX", MEMERRMSG, "ERRGCMM", "ERRERR"};
-  lua_pushstring(L, codes[code]);
+static const char *const statcodes[] = {"OK", "YIELD", "ERRRUN",
+    "ERRSYNTAX", MEMERRMSG, "ERRGCMM", "ERRERR"};
+
+/*
+** Avoid these stat codes from being collected, to avoid possible
+** memory error when pushing them.
+*/
+static void regcodes (lua_State *L) {
+  unsigned int i;
+  for (i = 0; i < sizeof(statcodes) / sizeof(statcodes[0]); i++) {
+    lua_pushboolean(L, 1);
+    lua_setfield(L, LUA_REGISTRYINDEX, statcodes[i]);
+  }
 }
 
 
@@ -1508,7 +1579,7 @@
       lua_pushnumber(L1, (lua_Number)getnum);
     }
     else if EQ("pushstatus") {
-      pushcode(L1, status);
+      lua_pushstring(L1, statcodes[status]);
     }
     else if EQ("pushstring") {
       lua_pushstring(L1, getstring);
@@ -1668,6 +1739,9 @@
       if (n == 0) n = lua_gettop(fs);
       lua_xmove(fs, ts, n);
     }
+    else if EQ("isyieldable") {
+      lua_pushboolean(L1, lua_isyieldable(lua_tothread(L1, getindex)));
+    }
     else if EQ("yield") {
       return lua_yield(L1, getnum);
     }
@@ -1710,7 +1784,7 @@
 
 
 static int Cfunck (lua_State *L, int status, lua_KContext ctx) {
-  pushcode(L, status);
+  lua_pushstring(L, statcodes[status]);
   lua_setglobal(L, "status");
   lua_pushinteger(L, ctx);
   lua_setglobal(L, "ctx");
@@ -1847,6 +1921,7 @@
   {"makeCfunc", makeCfunc},
   {"totalmem", mem_query},
   {"alloccount", alloc_count},
+  {"allocfailnext", alloc_failnext},
   {"trick", settrick},
   {"udataval", udataval},
   {"unref", unref},
@@ -1865,6 +1940,9 @@
   void *ud;
   lua_atpanic(L, &tpanic);
   lua_setwarnf(L, &warnf, L);
+  lua_pushboolean(L, 0);
+  lua_setglobal(L, "_WARN");  /* _WARN = false */
+  regcodes(L);
   atexit(checkfinalmem);
   lua_assert(lua_getallocf(L, &ud) == debug_realloc);
   lua_assert(ud == cast_voidp(&l_memcontrol));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/ltests/ltests.h 
new/lua-5.4.1-tests/ltests/ltests.h
--- old/lua-5.4.0-tests/ltests/ltests.h 2020-06-18 16:25:54.000000000 +0200
+++ new/lua-5.4.1-tests/ltests/ltests.h 2020-09-30 11:36:51.000000000 +0200
@@ -20,9 +20,7 @@
 
 
 /* turn on assertions */
-#undef NDEBUG
-#include <assert.h>
-#define lua_assert(c)           assert(c)
+#define LUAI_ASSERT
 
 
 
@@ -53,6 +51,7 @@
 
 /* memory-allocator control variables */
 typedef struct Memcontrol {
+  int failnext;
   unsigned long numblocks;
   unsigned long total;
   unsigned long maxmem;
@@ -74,7 +73,13 @@
 /*
 ** Function to traverse and check all memory used by Lua
 */
-int lua_checkmemory (lua_State *L);
+LUAI_FUNC int lua_checkmemory (lua_State *L);
+
+/*
+** Function to print an object GC-friendly
+*/
+struct GCObject;
+LUAI_FUNC void lua_printobj (lua_State *L, struct GCObject *o);
 
 
 /* test for lock/unlock */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/main.lua new/lua-5.4.1-tests/main.lua
--- old/lua-5.4.0-tests/main.lua        2020-06-18 16:25:55.000000000 +0200
+++ new/lua-5.4.1-tests/main.lua        2020-09-30 11:36:54.000000000 +0200
@@ -393,12 +393,12 @@
   -- testing 'warn'
   warn("@store")
   warn("@123", "456", "789")
-  assert(_WARN == "@123456789"); _WARN = nil
+  assert(_WARN == "@123456789"); _WARN = false
 
   warn("zip", "", " ", "zap")
-  assert(_WARN == "zip zap"); _WARN = nil
+  assert(_WARN == "zip zap"); _WARN = false
   warn("ZIP", "", " ", "ZAP")
-  assert(_WARN == "ZIP ZAP"); _WARN = nil
+  assert(_WARN == "ZIP ZAP"); _WARN = false
   warn("@normal")
 end
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/nextvar.lua 
new/lua-5.4.1-tests/nextvar.lua
--- old/lua-5.4.0-tests/nextvar.lua     2020-06-18 16:25:55.000000000 +0200
+++ new/lua-5.4.1-tests/nextvar.lua     2020-09-30 11:36:54.000000000 +0200
@@ -88,6 +88,7 @@
     arr[1 + sa + sh + 1] = "}"
     local prog = table.concat(arr)
     local f = assert(load(prog))
+    collectgarbage("stop")
     f()    -- call once to ensure stack space
     -- make sure table is not resized after being created
     if sa == 0 or sh == 0 then
@@ -97,6 +98,7 @@
     end
     local t = f()
     T.alloccount();
+    collectgarbage("restart")
     assert(#t == sa)
     check(t, sa, mp2(sh))
   end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lua-5.4.0-tests/strings.lua 
new/lua-5.4.1-tests/strings.lua
--- old/lua-5.4.0-tests/strings.lua     2020-06-18 16:25:55.000000000 +0200
+++ new/lua-5.4.1-tests/strings.lua     2020-09-30 11:36:54.000000000 +0200
@@ -438,7 +438,7 @@
 
   -- formats %U, %f, %I already tested elsewhere
 
-  local blen = 400    -- internal buffer length in 'luaO_pushfstring'
+  local blen = 200    -- internal buffer length in 'luaO_pushfstring'
 
   local function callpfs (op, fmt, n)
     local x = {T.testC("pushfstring" .. op .. "; return *", fmt, n)}

++++++ lua-5.4.0-tests.tar.gz -> lua-5.4.1.tar.gz ++++++
++++ 60560 lines of diff (skipped)


Reply via email to