Skip to content

Commit bbc1dae

Browse files
committed
tests/lapi: add builtin tests
The commit adds tests for Lua 5.1 builtin functions except the following functions: `print`, `pcall`, `xpcall`, `type`.
1 parent 972406b commit bbc1dae

23 files changed

+1046
-0
lines changed

tests/lapi/builtin_assert_test.lua

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Synopsis: assert(v [, message])
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
local MAX_INT = test_lib.MAX_INT
14+
15+
local function TestOneInput(buf)
16+
local fdp = luzer.FuzzedDataProvider(buf)
17+
local max_len = fdp:consume_integer(0, MAX_INT)
18+
local message = fdp:consume_string(max_len)
19+
local v = fdp:consume_boolean()
20+
local ok, _ = pcall(assert, v, message)
21+
assert(ok == v)
22+
end
23+
24+
local args = {
25+
artifact_prefix = "builtin_assert_",
26+
}
27+
luzer.Fuzz(TestOneInput, nil, args)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
--[=[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Synopsis: collectgarbage([opt [, arg]])
9+
]]=]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
14+
local unpack = unpack or table.unpack
15+
16+
local gc_mode = {
17+
"collect",
18+
"count",
19+
"restart",
20+
"step",
21+
"stop",
22+
}
23+
24+
if test_lib.lua_version() == "LuaJIT" then
25+
table.insert(gc_mode, "setpause")
26+
table.insert(gc_mode, "setstepmul")
27+
else
28+
table.insert(gc_mode, "isrunning")
29+
table.insert(gc_mode, "incremental")
30+
table.insert(gc_mode, "generational")
31+
end
32+
33+
local function TestOneInput(buf)
34+
local fdp = luzer.FuzzedDataProvider(buf)
35+
local mode = fdp:oneof(gc_mode)
36+
local MAX_INT = test_lib.MAX_INT
37+
local arg = {}
38+
if mode == "step" or
39+
mode == "setpause" or
40+
mode == "setstepmul" then
41+
table.insert(arg, fdp:consume_integer(0, MAX_INT))
42+
end
43+
-- This option can be followed by two numbers: the
44+
-- garbage-collector minor multiplier and the major multiplier.
45+
if mode == "generational" then
46+
table.insert(arg, fdp:consume_integer(0, MAX_INT))
47+
end
48+
-- This option can be followed by three numbers: the
49+
-- garbage-collector pause, the step multiplier, and the step
50+
-- size
51+
if mode == "incremental" then
52+
table.insert(arg, fdp:consume_integer(0, MAX_INT))
53+
end
54+
collectgarbage(mode, unpack(arg))
55+
end
56+
57+
local args = {
58+
artifact_prefix = "builtin_collectgarbage_",
59+
}
60+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/builtin_concat_test.lua

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
2.5.4 – Concatenation
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Recording of __concat in GC64 mode,
9+
https://github.com/LuaJIT/LuaJIT/issues/839
10+
11+
Bug: Unbalanced Stack After Hot Instruction error on table concatenation,
12+
https://github.com/LuaJIT/LuaJIT/issues/690
13+
14+
LJ_GC64: Fix lua_concat(),
15+
https://github.com/LuaJIT/LuaJIT/issues/881
16+
17+
Buffer overflow in string concatenation,
18+
https://github.com/lua/lua/commit/5853c37a83ec66ccb45094f9aeac23dfdbcde671
19+
20+
Wrong assert when reporting concatenation errors
21+
(manifests only when Lua is compiled in debug mode).
22+
https://www.lua.org/bugs.html#5.2.2-3
23+
24+
Wrong error message in some concatenations,
25+
https://www.lua.org/bugs.html#5.1.2-5
26+
27+
Concat metamethod converts numbers to strings,
28+
https://www.lua.org/bugs.html#5.1.1-8
29+
30+
String concatenation may cause arithmetic overflow, leading to
31+
a buffer overflow,
32+
https://www.lua.org/bugs.html#5.0.2-1
33+
]]
34+
35+
local luzer = require("luzer")
36+
local test_lib = require("lib")
37+
38+
local function TestOneInput(buf)
39+
local fdp = luzer.FuzzedDataProvider(buf)
40+
local str = fdp:consume_string(test_lib.MAX_STR_LEN)
41+
if str == nil then return -1 end
42+
local str_chars = {}
43+
str:gsub(".", function(c) table.insert(str_chars, c) end)
44+
45+
local str_concat = ""
46+
for _, c in ipairs(str_chars) do
47+
str_concat = str_concat .. c
48+
end
49+
assert(str_concat == str)
50+
end
51+
52+
local args = {
53+
artifact_prefix = "builtin_concat_",
54+
}
55+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/builtin_dofile_test.lua

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Synopsis: dofile([filename])
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
14+
local function TestOneInput(buf)
15+
local chunk_filename = os.tmpname()
16+
local fh = io.open(chunk_filename, "w")
17+
fh:write(buf)
18+
fh:close()
19+
pcall(dofile, chunk_filename)
20+
os.remove(chunk_filename)
21+
end
22+
23+
local args = {
24+
artifact_prefix = "builtin_dofile_",
25+
}
26+
-- lj_bcread.c:123: bcread_byte: buffer read overflow
27+
if test_lib.lua_version() == "LuaJIT" then
28+
args.only_ascii = 1
29+
end
30+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/builtin_dostring_test.lua

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
]]
8+
9+
local luzer = require("luzer")
10+
local test_lib = require("lib")
11+
local MAX_INT = test_lib.MAX_INT
12+
13+
local function TestOneInput(buf)
14+
local fdp = luzer.FuzzedDataProvider(buf)
15+
local max_len = fdp:consume_integer(0, MAX_INT)
16+
local str = fdp:consume_string(max_len)
17+
pcall(loadstring, str)
18+
end
19+
20+
local args = {
21+
artifact_prefix = "builtin_dostring_",
22+
}
23+
-- lj_bcread.c:123: bcread_byte: buffer read overflow
24+
if test_lib.lua_version() == "LuaJIT" then
25+
args.only_ascii = 1
26+
end
27+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/builtin_error_test.lua

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Synopsis: error(message [, level])
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
local MAX_INT = test_lib.MAX_INT
14+
15+
local function escape_pattern(text)
16+
return (text:gsub("[-.+%[%]()$^%%?*]", "%%%1"))
17+
end
18+
19+
local function TestOneInput(buf)
20+
local fdp = luzer.FuzzedDataProvider(buf)
21+
local level = fdp:consume_integer(0, MAX_INT)
22+
local message_len = fdp:consume_integer(0, MAX_INT)
23+
local message = fdp:consume_string(message_len)
24+
local ok, err = pcall(error, message, level)
25+
assert(ok == false)
26+
-- Escape message to avoid error "invalid pattern capture".
27+
assert(err:match(escape_pattern(message)) == message)
28+
end
29+
30+
local args = {
31+
artifact_prefix = "builtin_error_",
32+
}
33+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/builtin_getfenv_test.lua

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
debug.getfenv does not check whether it has an argument,
9+
https://www.lua.org/bugs.html#5.1.4-5
10+
11+
module may change the environment of a C function,
12+
https://www.lua.org/bugs.html#5.1.3-11
13+
14+
UBSan warning for too big/small getfenv/setfenv level,
15+
https://github.com/LuaJIT/LuaJIT/issues/1329
16+
17+
Synopsis: getfenv([f])
18+
]]
19+
20+
local luzer = require("luzer")
21+
local test_lib = require("lib")
22+
23+
-- Lua 5.2: Functions setfenv and getfenv were removed, because
24+
-- of the changes in environments.
25+
if test_lib.lua_current_version_ge_than(5, 2) then
26+
print("Unsupported version.")
27+
os.exit(0)
28+
end
29+
30+
local function TestOneInput(buf)
31+
local fdp = luzer.FuzzedDataProvider(buf)
32+
local level = fdp:consume_integer(0, test_lib.MAX_INT)
33+
local fenv, err = pcall(getfenv, level)
34+
if err then
35+
return -1
36+
end
37+
local magic_str = fdp:consume_string(test_lib.MAX_STR_LEN)
38+
fenv["magic"] = magic_str
39+
setfenv(level, fenv)
40+
assert(getfenv(level).magic == magic_str)
41+
end
42+
43+
local args = {
44+
artifact_prefix = "builtin_getfenv_",
45+
}
46+
luzer.Fuzz(TestOneInput, nil, args)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Incorrect recording of getmetatable() for IO handlers,
9+
https://github.com/LuaJIT/LuaJIT/issues/1279
10+
11+
Synopsis: getmetatable(object)
12+
]]
13+
14+
local luzer = require("luzer")
15+
local test_lib = require("lib")
16+
17+
local function TestOneInput(buf)
18+
local tbl = {}
19+
local fdp = luzer.FuzzedDataProvider(buf)
20+
-- Build a random table and set a known key to it to check
21+
-- it's presence in metatable.
22+
local MAX_N = 100
23+
local count = fdp:consume_integer(0, MAX_N)
24+
local mt = fdp:consume_integers(test_lib.MIN_INT, test_lib.MAX_INT, count)
25+
setmetatable(tbl, mt)
26+
local metatable = getmetatable(tbl)
27+
assert(test_lib.arrays_equal(metatable, mt))
28+
end
29+
30+
local args = {
31+
artifact_prefix = "builtin_getmetatable_",
32+
}
33+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/builtin_ipairs_test.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.1 – Basic Functions
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Synopsis: ipairs(t)
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
14+
local function TestOneInput(buf)
15+
local fdp = luzer.FuzzedDataProvider(buf)
16+
local MAX_N = 1000
17+
local count = fdp:consume_integer(0, MAX_N)
18+
local tbl = fdp:consume_integers(test_lib.MIN_INT, test_lib.MAX_INT, count)
19+
for i, v in ipairs(tbl) do
20+
assert(type(i) == "number")
21+
assert(type(v) == "number")
22+
end
23+
end
24+
25+
local args = {
26+
artifact_prefix = "builtin_ipairs_",
27+
}
28+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/builtin_length_test.lua

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
2.5.5 – The Length Operator
6+
https://www.lua.org/manual/5.1/manual.html
7+
8+
Table length computation overflows for sequences larger than
9+
2^31 elements, https://www.lua.org/bugs.html#5.3.4-3
10+
]]
11+
12+
local luzer = require("luzer")
13+
local test_lib = require("lib")
14+
15+
local unpack = unpack or table.unpack
16+
17+
local function TestOneInput(buf)
18+
local fdp = luzer.FuzzedDataProvider(buf)
19+
20+
local str = fdp:consume_string(test_lib.MAX_STR_LEN)
21+
if str == nil then return -1 end
22+
local str_chars = {}
23+
str:gsub(".", function(c) table.insert(str_chars, c) end)
24+
25+
assert(#str == select("#", unpack(str_chars)))
26+
assert(#str == string.len(str))
27+
assert(#str == str:len())
28+
assert(#str_chars == str:len())
29+
end
30+
31+
local args = {
32+
artifact_prefix = "builtin_length_",
33+
}
34+
luzer.Fuzz(TestOneInput, nil, args)

0 commit comments

Comments
 (0)