add Lua sandbox with timer system (milestones 1-5 complete)
This commit is contained in:
11
sandbox-test/scripts/scripts/test_module.lua
Normal file
11
sandbox-test/scripts/scripts/test_module.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
-- Test module for SafeRequire tests
|
||||
local M = {}
|
||||
|
||||
M.value = 42
|
||||
M.name = "test_module"
|
||||
|
||||
function M.add(a, b)
|
||||
return a + b
|
||||
end
|
||||
|
||||
return M
|
||||
5
sandbox-test/scripts/test_bytecode_rejected.lua
Normal file
5
sandbox-test/scripts/test_bytecode_rejected.lua
Normal file
@@ -0,0 +1,5 @@
|
||||
-- This script tests that text loading works
|
||||
-- The actual bytecode rejection test is done from C++ side
|
||||
-- by attempting to load a bytecode string directly
|
||||
|
||||
print("PASS: Text loading works")
|
||||
12
sandbox-test/scripts/test_cpu_limit.lua
Normal file
12
sandbox-test/scripts/test_cpu_limit.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
-- This script runs an infinite loop
|
||||
-- It should be stopped by the instruction limit hook
|
||||
|
||||
local count = 0
|
||||
|
||||
while true do
|
||||
count = count + 1
|
||||
-- This loop should be interrupted by instruction hook
|
||||
end
|
||||
|
||||
-- Should never reach here
|
||||
error("FAIL: CPU limit not enforced - loop completed")
|
||||
26
sandbox-test/scripts/test_globals_removed.lua
Normal file
26
sandbox-test/scripts/test_globals_removed.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
-- Test that dangerous globals are nil
|
||||
-- This script should run successfully if sandbox is properly configured
|
||||
-- Note: 'require' is intentionally NOT in this list because the sandbox
|
||||
-- provides a safe version when app_path is configured
|
||||
|
||||
local dangerous = {
|
||||
"os", "io", "debug", "package", "ffi", "jit",
|
||||
"dofile", "loadfile", "load", "loadstring",
|
||||
"rawget", "rawset", "rawequal", "rawlen",
|
||||
"collectgarbage", "newproxy"
|
||||
}
|
||||
|
||||
local failed = {}
|
||||
|
||||
for _, name in ipairs(dangerous) do
|
||||
local value = _G[name]
|
||||
if value ~= nil then
|
||||
table.insert(failed, name .. " (is " .. type(value) .. ")")
|
||||
end
|
||||
end
|
||||
|
||||
if #failed > 0 then
|
||||
error("FAIL: These globals should be nil: " .. table.concat(failed, ", "))
|
||||
end
|
||||
|
||||
print("PASS: All dangerous globals removed")
|
||||
20
sandbox-test/scripts/test_memory_limit.lua
Normal file
20
sandbox-test/scripts/test_memory_limit.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
-- This script intentionally tries to exhaust memory
|
||||
-- When run with a 512KB limit, it should fail before completing
|
||||
|
||||
local t = {}
|
||||
local i = 0
|
||||
|
||||
while true do
|
||||
i = i + 1
|
||||
-- Each string is 100KB
|
||||
t[i] = string.rep("x", 100000)
|
||||
|
||||
-- Safety check - if we get past 100 iterations with 512KB limit,
|
||||
-- something is wrong
|
||||
if i > 100 then
|
||||
error("FAIL: Should have hit memory limit by now (allocated ~10MB)")
|
||||
end
|
||||
end
|
||||
|
||||
-- Should never reach here
|
||||
error("FAIL: Memory limit not enforced")
|
||||
33
sandbox-test/scripts/test_metatable_protected.lua
Normal file
33
sandbox-test/scripts/test_metatable_protected.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
-- Test that metatables are protected from manipulation
|
||||
|
||||
-- Test 1: String metatable should return protection value, not actual metatable
|
||||
local mt = getmetatable("")
|
||||
if mt ~= "string" then
|
||||
error("FAIL: string metatable should return 'string', got " .. tostring(mt))
|
||||
end
|
||||
|
||||
-- Test 2: Cannot add new globals
|
||||
local ok, err = pcall(function()
|
||||
_G.my_new_global = "test"
|
||||
end)
|
||||
if ok then
|
||||
error("FAIL: Should not be able to add new globals")
|
||||
end
|
||||
|
||||
-- Test 3: Cannot modify existing globals
|
||||
local ok2, err2 = pcall(function()
|
||||
_G.print = nil
|
||||
end)
|
||||
if ok2 then
|
||||
error("FAIL: Should not be able to modify print")
|
||||
end
|
||||
|
||||
-- Test 4: Cannot replace math table
|
||||
local ok3, err3 = pcall(function()
|
||||
_G.math = {}
|
||||
end)
|
||||
if ok3 then
|
||||
error("FAIL: Should not be able to replace math")
|
||||
end
|
||||
|
||||
print("PASS: Metatables protected")
|
||||
158
sandbox-test/scripts/test_safe_operations.lua
Normal file
158
sandbox-test/scripts/test_safe_operations.lua
Normal file
@@ -0,0 +1,158 @@
|
||||
-- Test that safe/normal Lua operations still work correctly
|
||||
|
||||
local function check(cond, msg)
|
||||
if not cond then
|
||||
error("FAIL: " .. msg)
|
||||
end
|
||||
end
|
||||
|
||||
-- ============================================
|
||||
-- MATH OPERATIONS
|
||||
-- ============================================
|
||||
local x = math.sin(1.5) + math.floor(3.7)
|
||||
check(type(x) == "number", "Math operations failed")
|
||||
|
||||
check(math.abs(-5) == 5, "math.abs failed")
|
||||
check(math.max(1, 2, 3) == 3, "math.max failed")
|
||||
check(math.min(1, 2, 3) == 1, "math.min failed")
|
||||
check(math.floor(3.9) == 3, "math.floor failed")
|
||||
check(math.ceil(3.1) == 4, "math.ceil failed")
|
||||
|
||||
-- ============================================
|
||||
-- STRING OPERATIONS
|
||||
-- ============================================
|
||||
local s = string.format("hello %d", 42)
|
||||
check(s == "hello 42", "string.format failed")
|
||||
|
||||
local upper = string.upper("test")
|
||||
check(upper == "TEST", "string.upper failed")
|
||||
|
||||
local lower = string.lower("TEST")
|
||||
check(lower == "test", "string.lower failed")
|
||||
|
||||
local sub = string.sub("hello", 2, 4)
|
||||
check(sub == "ell", "string.sub failed")
|
||||
|
||||
local len = string.len("hello")
|
||||
check(len == 5, "string.len failed")
|
||||
|
||||
local rep = string.rep("ab", 3)
|
||||
check(rep == "ababab", "string.rep failed")
|
||||
|
||||
local rev = string.reverse("hello")
|
||||
check(rev == "olleh", "string.reverse failed")
|
||||
|
||||
-- ============================================
|
||||
-- TABLE OPERATIONS
|
||||
-- ============================================
|
||||
local t = {1, 2, 3}
|
||||
table.insert(t, 4)
|
||||
check(#t == 4, "table.insert failed")
|
||||
check(t[4] == 4, "table.insert value failed")
|
||||
|
||||
local removed = table.remove(t)
|
||||
check(removed == 4, "table.remove failed")
|
||||
check(#t == 3, "table.remove length failed")
|
||||
|
||||
local t2 = {3, 1, 2}
|
||||
table.sort(t2)
|
||||
check(t2[1] == 1 and t2[2] == 2 and t2[3] == 3, "table.sort failed")
|
||||
|
||||
local concat = table.concat({"a", "b", "c"}, ",")
|
||||
check(concat == "a,b,c", "table.concat failed")
|
||||
|
||||
-- ============================================
|
||||
-- ITERATION
|
||||
-- ============================================
|
||||
local count = 0
|
||||
for i, v in ipairs({1, 2, 3, 4}) do
|
||||
count = count + 1
|
||||
end
|
||||
check(count == 4, "ipairs iteration failed")
|
||||
|
||||
count = 0
|
||||
for k, v in pairs({a=1, b=2, c=3}) do
|
||||
count = count + 1
|
||||
end
|
||||
check(count == 3, "pairs iteration failed")
|
||||
|
||||
-- next function
|
||||
local t3 = {a=1, b=2}
|
||||
local k, v = next(t3)
|
||||
check(k ~= nil and v ~= nil, "next function failed")
|
||||
|
||||
-- ============================================
|
||||
-- ERROR HANDLING
|
||||
-- ============================================
|
||||
local ok, err = pcall(function()
|
||||
error("test error")
|
||||
end)
|
||||
check(not ok, "pcall should return false for error")
|
||||
check(err:find("test error"), "Error message should contain 'test error'")
|
||||
|
||||
local ok2, result = pcall(function()
|
||||
return 42
|
||||
end)
|
||||
check(ok2 and result == 42, "pcall should return success value")
|
||||
|
||||
-- xpcall with traceback
|
||||
local ok3, err3 = xpcall(function()
|
||||
error("xpcall test")
|
||||
end, function(e)
|
||||
return "caught: " .. tostring(e)
|
||||
end)
|
||||
check(not ok3, "xpcall should return false for error")
|
||||
check(err3:find("caught"), "xpcall error handler should run")
|
||||
|
||||
-- ============================================
|
||||
-- TYPE CHECKS
|
||||
-- ============================================
|
||||
check(type({}) == "table", "type table failed")
|
||||
check(type("") == "string", "type string failed")
|
||||
check(type(123) == "number", "type number failed")
|
||||
check(type(true) == "boolean", "type boolean failed")
|
||||
check(type(nil) == "nil", "type nil failed")
|
||||
check(type(function() end) == "function", "type function failed")
|
||||
|
||||
-- ============================================
|
||||
-- CONVERSION
|
||||
-- ============================================
|
||||
check(tonumber("42") == 42, "tonumber string failed")
|
||||
check(tonumber("3.14") == 3.14, "tonumber float failed")
|
||||
check(tonumber("abc") == nil, "tonumber invalid failed")
|
||||
check(tonumber(42) == 42, "tonumber number failed")
|
||||
|
||||
check(tostring(42) == "42", "tostring number failed")
|
||||
check(tostring(true) == "true", "tostring boolean failed")
|
||||
check(type(tostring({})) == "string", "tostring table failed")
|
||||
|
||||
-- ============================================
|
||||
-- SELECT
|
||||
-- ============================================
|
||||
local a, b = select(2, 1, 2, 3)
|
||||
check(a == 2 and b == 3, "select failed")
|
||||
check(select("#", 1, 2, 3, 4) == 4, "select # failed")
|
||||
|
||||
-- ============================================
|
||||
-- ASSERT
|
||||
-- ============================================
|
||||
local ok4, err4 = pcall(function()
|
||||
assert(true, "should not fail")
|
||||
end)
|
||||
check(ok4, "assert true failed")
|
||||
|
||||
local ok5, err5 = pcall(function()
|
||||
assert(false, "intentional fail")
|
||||
end)
|
||||
check(not ok5, "assert false should fail")
|
||||
check(err5:find("intentional fail"), "assert message wrong")
|
||||
|
||||
-- ============================================
|
||||
-- UTF8 (if available)
|
||||
-- ============================================
|
||||
if utf8 then
|
||||
local len = utf8.len("hello")
|
||||
check(len == 5, "utf8.len failed")
|
||||
end
|
||||
|
||||
print("PASS: All safe operations work correctly")
|
||||
18
sandbox-test/scripts/test_string_dump_removed.lua
Normal file
18
sandbox-test/scripts/test_string_dump_removed.lua
Normal file
@@ -0,0 +1,18 @@
|
||||
-- Test that string.dump is removed
|
||||
-- string.dump can be used to create bytecode from functions,
|
||||
-- which could be used to bypass sandbox restrictions
|
||||
|
||||
if string.dump ~= nil then
|
||||
error("FAIL: string.dump should be nil but exists")
|
||||
end
|
||||
|
||||
-- Also verify string table exists and other functions work
|
||||
if string.upper == nil then
|
||||
error("FAIL: string.upper should exist")
|
||||
end
|
||||
|
||||
if string.format == nil then
|
||||
error("FAIL: string.format should exist")
|
||||
end
|
||||
|
||||
print("PASS: string.dump removed, other string functions intact")
|
||||
Reference in New Issue
Block a user