summaryrefslogtreecommitdiff
path: root/zig-lua/lua-5.4.7/testes/cstack.lua
diff options
context:
space:
mode:
Diffstat (limited to 'zig-lua/lua-5.4.7/testes/cstack.lua')
-rw-r--r--zig-lua/lua-5.4.7/testes/cstack.lua197
1 files changed, 197 insertions, 0 deletions
diff --git a/zig-lua/lua-5.4.7/testes/cstack.lua b/zig-lua/lua-5.4.7/testes/cstack.lua
new file mode 100644
index 0000000..97afe9f
--- /dev/null
+++ b/zig-lua/lua-5.4.7/testes/cstack.lua
@@ -0,0 +1,197 @@
+-- $Id: testes/cstack.lua $
+-- See Copyright Notice in file all.lua
+
+
+local tracegc = require"tracegc"
+
+print"testing stack overflow detection"
+
+-- Segmentation faults in these tests probably result from a C-stack
+-- overflow. To avoid these errors, you should set a smaller limit for
+-- the use of C stack by Lua, by changing the constant 'LUAI_MAXCCALLS'.
+-- Alternatively, you can ensure a larger stack for the program.
+
+
+local function checkerror (msg, f, ...)
+ local s, err = pcall(f, ...)
+ assert(not s and string.find(err, msg))
+end
+
+do print("testing stack overflow in message handling")
+ local count = 0
+ local function loop (x, y, z)
+ count = count + 1
+ return 1 + loop(x, y, z)
+ end
+ tracegc.stop() -- __gc should not be called with a full stack
+ local res, msg = xpcall(loop, loop)
+ tracegc.start()
+ assert(msg == "error in error handling")
+ print("final count: ", count)
+end
+
+
+-- bug since 2.5 (C-stack overflow in recursion inside pattern matching)
+do print("testing recursion inside pattern matching")
+ local function f (size)
+ local s = string.rep("a", size)
+ local p = string.rep(".?", size)
+ return string.match(s, p)
+ end
+ local m = f(80)
+ assert(#m == 80)
+ checkerror("too complex", f, 2000)
+end
+
+
+do print("testing stack-overflow in recursive 'gsub'")
+ local count = 0
+ local function foo ()
+ count = count + 1
+ string.gsub("a", ".", foo)
+ end
+ checkerror("stack overflow", foo)
+ print("final count: ", count)
+
+ print("testing stack-overflow in recursive 'gsub' with metatables")
+ local count = 0
+ local t = setmetatable({}, {__index = foo})
+ foo = function ()
+ count = count + 1
+ string.gsub("a", ".", t)
+ end
+ checkerror("stack overflow", foo)
+ print("final count: ", count)
+end
+
+
+do -- bug in 5.4.0
+ print("testing limits in coroutines inside deep calls")
+ local count = 0
+ local lim = 1000
+ local function stack (n)
+ if n > 0 then return stack(n - 1) + 1
+ else coroutine.wrap(function ()
+ count = count + 1
+ stack(lim)
+ end)()
+ end
+ end
+
+ local st, msg = xpcall(stack, function () return "ok" end, lim)
+ assert(not st and msg == "ok")
+ print("final count: ", count)
+end
+
+
+do -- bug since 5.4.0
+ local count = 0
+ print("chain of 'coroutine.close'")
+ -- create N coroutines forming a list so that each one, when closed,
+ -- closes the previous one. (With a large enough N, previous Lua
+ -- versions crash in this test.)
+ local coro = false
+ for i = 1, 1000 do
+ local previous = coro
+ coro = coroutine.create(function()
+ local cc <close> = setmetatable({}, {__close=function()
+ count = count + 1
+ if previous then
+ assert(coroutine.close(previous))
+ end
+ end})
+ coroutine.yield() -- leaves 'cc' pending to be closed
+ end)
+ assert(coroutine.resume(coro)) -- start it and run until it yields
+ end
+ local st, msg = coroutine.close(coro)
+ assert(not st and string.find(msg, "C stack overflow"))
+ print("final count: ", count)
+end
+
+
+do
+ print("nesting of resuming yielded coroutines")
+ local count = 0
+
+ local function body ()
+ coroutine.yield()
+ local f = coroutine.wrap(body)
+ f(); -- start new coroutine (will stop in previous yield)
+ count = count + 1
+ f() -- call it recursively
+ end
+
+ local f = coroutine.wrap(body)
+ f()
+ assert(not pcall(f))
+ print("final count: ", count)
+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
+ local LIM = -1 -- will store N just before stack overflow
+
+ -- trace stack size; after stack overflow, it should be
+ -- the maximum allowed stack size.
+ local stack1
+ local dummy
+
+ local function err(msg)
+ assert(string.find(msg, "stack overflow"))
+ local _, stacknow = T.stacklevel()
+ assert(stacknow == stack1 + 200)
+ end
+
+ -- When LIM==-1, the 'if' is not executed, so this function only
+ -- counts and stores the stack limits up to overflow. Then, LIM
+ -- becomes N, and then the 'if' code is run when the stack is
+ -- full. Then, there is a stack overflow inside 'xpcall', after which
+ -- the stack must have been restored back to its maximum normal size.
+ local function f()
+ dummy, stack1 = T.stacklevel()
+ if N == LIM then
+ xpcall(f, err)
+ local _, stacknow = T.stacklevel()
+ assert(stacknow == stack1)
+ return
+ end
+ N = N + 1
+ f()
+ end
+
+ local topB, sizeB -- top and size Before overflow
+ local topA, sizeA -- top and size After overflow
+ topB, sizeB = T.stacklevel()
+ tracegc.stop() -- __gc should not be called with a full stack
+ xpcall(f, err)
+ tracegc.start()
+ topA, sizeA = T.stacklevel()
+ -- sizes should be comparable
+ assert(topA == topB and sizeA < sizeB * 2)
+ print(string.format("maximum stack size: %d", stack1))
+ LIM = N -- will stop recursion at maximum level
+ N = 0 -- to count again
+ tracegc.stop() -- __gc should not be called with a full stack
+ f()
+ tracegc.start()
+ print"+"
+end
+
+print'OK'