Skip to content

Commit 259b7c2

Browse files
committed
tests/lapi: table tests
The patch adds a fuzzing tests for Lua table functions.
1 parent bfac9d7 commit 259b7c2

12 files changed

+391
-0
lines changed

.luacheckrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ files["tests/capi/luaL_loadbuffer_proto/preamble.lua"] = {
55
"211",
66
},
77
}
8+
9+
globals = {
10+
table = {
11+
fields = { "create" }
12+
}
13+
}

tests/lapi/table_concat_test.lua

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--[=[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.5 – Table Manipulation,
6+
https://www.lua.org/manual/5.1/manual.html#5.5
7+
8+
Infinite loop on table lookup,
9+
https://github.com/LuaJIT/LuaJIT/issues/494
10+
11+
Synopsis: table.concat(list [, sep [, i [, j]]])
12+
--]=]
13+
14+
local luzer = require("luzer")
15+
local test_lib = require("lib")
16+
17+
local function TestOneInput(buf, _size)
18+
local fdp = luzer.FuzzedDataProvider(buf)
19+
local str = fdp:consume_string(test_lib.MAX_STR_LEN)
20+
local tbl_size = #str
21+
if tbl_size <= 1 then return -1 end
22+
23+
-- Split string to a table.
24+
local tbl = {}
25+
str:gsub(".", function(c)
26+
table.insert(tbl, c)
27+
end)
28+
assert(#tbl, tbl_size)
29+
30+
-- Join table to a string.
31+
local j = fdp:consume_integer(1, tbl_size)
32+
local i = fdp:consume_integer(1, j)
33+
local sep = ""
34+
assert(string.sub(str, i, j) == table.concat(tbl, sep, i, j))
35+
end
36+
37+
local args = {
38+
artifact_prefix = "table_concat_",
39+
}
40+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_create_test.lua

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
Bad lookup generated by lj_record_idx in GC64,
6+
https://github.com/LuaJIT/LuaJIT/issues/840
7+
8+
Synopsis:
9+
LuaJIT: table.new(narray, nhash)
10+
PUC Rio Lua: table.create(narray, nhash)
11+
]]
12+
13+
local luzer = require("luzer")
14+
local test_lib = require("lib")
15+
16+
local table_create
17+
if test_lib.lua_version() == "LuaJIT" then
18+
table_create = require("table.new")
19+
elseif test_lib.lua_current_version_lt_than(5, 5) then
20+
-- New function 'table.create()' in PUC Rio Lua,
21+
-- https://github.com/lua/lua/commit/3e9dbe143d3338f5f13a5e421ea593adff482da0
22+
table_create = table.create
23+
else
24+
print("Unsupported version.")
25+
os.exit(0)
26+
end
27+
28+
local function TestOneInput(buf)
29+
local fdp = luzer.FuzzedDataProvider(buf)
30+
-- Beware, huge number triggers OOM or table overflow.
31+
local MAX_N = 1000
32+
local narray = fdp:consume_integer(0, MAX_N)
33+
local nhash = fdp:consume_integer(0, MAX_N)
34+
local _ = table_create(narray, nhash) -- luacheck: no unused
35+
end
36+
37+
local args = {
38+
artifact_prefix = "table_create_",
39+
}
40+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_foreach_test.lua

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.4 – Table Manipulation,
6+
https://www.lua.org/manual/5.0/manual.html#5.4
7+
8+
Bad loop initialization in table.foreach(),
9+
https://github.com/LuaJIT/LuaJIT/issues/844
10+
11+
string.dump(table.foreach) will trigger an assert,
12+
https://github.com/LuaJIT/LuaJIT/issues/1038
13+
14+
Synopsis: table.foreach(table, f)
15+
]]
16+
17+
local luzer = require("luzer")
18+
local test_lib = require("lib")
19+
20+
-- Function `table.foreach` is deprecated in Lua 5.1.
21+
if test_lib.lua_current_version_ge_than(5, 2) then
22+
print("Unsupported version.")
23+
os.exit(0)
24+
end
25+
26+
local function TestOneInput(buf, _size)
27+
local fdp = luzer.FuzzedDataProvider(buf)
28+
local count = fdp:consume_integer(1, test_lib.MAX_INT)
29+
local tbl = fdp:consume_strings(test_lib.MAX_STR_LEN, count)
30+
local i = 0
31+
local fn = function(_idx, _v) i = i + 1 end
32+
table.foreach(tbl, fn)
33+
assert(table.maxn(tbl) == i)
34+
end
35+
36+
local args = {
37+
artifact_prefix = "table_foreach_",
38+
}
39+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_foreachi_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.4 – Table Manipulation,
6+
https://www.lua.org/manual/5.0/manual.html#5.4
7+
8+
Synopsis: table.foreachi(table, f)
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
14+
-- Function `table.foreach` is deprecated in Lua 5.1.
15+
if test_lib.lua_current_version_ge_than(5, 2) then
16+
print("Unsupported version.")
17+
os.exit(0)
18+
end
19+
20+
local function TestOneInput(buf, _size)
21+
local fdp = luzer.FuzzedDataProvider(buf)
22+
local count = fdp:consume_integer(1, test_lib.MAX_INT)
23+
local tbl = fdp:consume_strings(test_lib.MAX_STR_LEN, count)
24+
local i = 0
25+
local fn = function(_idx, _v) i = i + 1 end
26+
table.foreachi(tbl, fn)
27+
assert(table.maxn(tbl) == i)
28+
end
29+
30+
local args = {
31+
artifact_prefix = "table_foreachi_",
32+
}
33+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_insert_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-2024, Sergey Bronnikov.
4+
5+
5.5 – Table Manipulation,
6+
https://www.lua.org/manual/5.1/manual.html#5.5
7+
8+
Synopsis: table.insert(list, [pos,] value)
9+
]]
10+
11+
local luzer = require("luzer")
12+
13+
local function TestOneInput(buf, _size)
14+
local len = string.len(buf)
15+
local tbl = {}
16+
local pos = 1
17+
buf:gsub(".", function(c)
18+
table.insert(tbl, pos, c)
19+
pos = pos + 1
20+
end)
21+
assert(pos, len)
22+
end
23+
24+
local args = {
25+
artifact_prefix = "table_insert_",
26+
}
27+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_maxn_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.5 – Table Manipulation,
6+
https://www.lua.org/manual/5.1/manual.html#5.5
7+
8+
Synopsis: table.maxn(table)
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
14+
if test_lib.lua_current_version_ge_than(5, 3) then
15+
print("Unsupported version.")
16+
os.exit(0)
17+
end
18+
19+
local function TestOneInput(buf)
20+
local fdp = luzer.FuzzedDataProvider(buf)
21+
local count = fdp:consume_integer(0, test_lib.MAX_INT64)
22+
local tbl = fdp:consume_strings(test_lib.MAX_STR_LEN, count)
23+
local maxn = table.maxn(tbl)
24+
assert(type(maxn) == "number")
25+
end
26+
27+
local args = {
28+
artifact_prefix = "table_maxn_",
29+
}
30+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_move_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+
6.6 – Table Manipulation,
6+
https://www.lua.org/manual/5.3/manual.html#6.6
7+
8+
Synopsis: table.move(a1, f, e, t [,a2])
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
14+
if test_lib.lua_version() ~= "LuaJIT" then
15+
print("Unsupported version.")
16+
os.exit(0)
17+
end
18+
19+
local function TestOneInput(buf, _size)
20+
local fdp = luzer.FuzzedDataProvider(buf)
21+
local count = fdp:consume_integer(0, test_lib.MAX_INT)
22+
local tbl = fdp:consume_strings(test_lib.MAX_STR_LEN, count)
23+
local tbl_len = #tbl
24+
local tbl_new= {}
25+
-- Move all items from the table `tbl` to the `tbl_new`.
26+
table.move(tbl, 1, tbl_len, 1, tbl_new)
27+
assert(tbl[1] == tbl_new[1])
28+
assert(tbl[tbl_len] == tbl_new[tbl_len])
29+
end
30+
31+
local args = {
32+
artifact_prefix = "table_move_",
33+
}
34+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_pack_test.lua

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
6.5 – Table Manipulation,
6+
https://www.lua.org/manual/5.2/manual.html#6.5
7+
8+
Synopsis: table.pack(...)
9+
]]
10+
11+
local luzer = require("luzer")
12+
local test_lib = require("lib")
13+
14+
if test_lib.lua_current_version_lt_than(5, 2) then
15+
print("Unsupported version.")
16+
os.exit(0)
17+
end
18+
19+
local unpack = unpack or table.unpack
20+
21+
local function TestOneInput(buf, _size)
22+
local fdp = luzer.FuzzedDataProvider(buf)
23+
-- Beware, huge number triggers 'too many results to unpack'.
24+
local MAX_N = 1000
25+
local count = fdp:consume_integer(1, MAX_N)
26+
local tbl = fdp:consume_integers(test_lib.MIN_INT, test_lib.MAX_INT, count)
27+
local packed = table.pack(unpack(tbl))
28+
assert(#packed == #tbl)
29+
assert(packed[1] == tbl[1])
30+
end
31+
32+
local args = {
33+
artifact_prefix = "table_pack_",
34+
}
35+
luzer.Fuzz(TestOneInput, nil, args)

tests/lapi/table_remove_test.lua

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--[[
2+
SPDX-License-Identifier: ISC
3+
Copyright (c) 2023-2025, Sergey Bronnikov.
4+
5+
5.5 – Table Manipulation,
6+
https://www.lua.org/manual/5.1/manual.html#5.5
7+
8+
table.remove removes last element of a table when given an
9+
out-of-bound index, https://www.lua.org/bugs.html#5.1.2-10
10+
11+
Synopsis: table.remove(list [, pos])
12+
]]
13+
14+
local luzer = require("luzer")
15+
local test_lib = require("lib")
16+
local MAX_INT = test_lib.MAX_INT
17+
18+
local function TestOneInput(buf, _size)
19+
local fdp = luzer.FuzzedDataProvider(buf)
20+
local max_len = fdp:consume_integer(0, MAX_INT)
21+
local str = fdp:consume_string(max_len)
22+
local tbl = {}
23+
str:gsub(".", function(c)
24+
table.insert(tbl, c)
25+
end)
26+
for _ = 1, #tbl do
27+
assert(tbl[1] == table.remove(tbl, 1))
28+
end
29+
assert(#tbl == 0)
30+
end
31+
32+
local args = {
33+
artifact_prefix = "table_remove_",
34+
}
35+
luzer.Fuzz(TestOneInput, nil, args)

0 commit comments

Comments
 (0)