You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lua沙箱技术求助:如何让沙箱代码调用自身自定义函数

沙箱无法调用自定义函数的修复方案

问题背景

练习25.8 图25.6《使用钩子阻止调用未授权函数》中的沙箱存在两个核心问题:

  1. 沙箱内代码无法调用自身定义的函数
  2. 提供的测试代码无法正常运行,无法将沙箱运行时的函数加入validfunc授权表

当前代码的核心问题

  1. 授权时机错误:原代码在沙箱代码运行完成后才将chunkEnv中的函数加入授权表,但运行时钩子已在执行检查,导致自定义函数调用直接报错
  2. 授权匹配逻辑错误:原代码用函数名作为validfunc的key,但钩子检查的是函数对象本身,两者不匹配
  3. 变量作用域问题:钩子函数中局部info变量未向外暴露,导致后续print操作出现nil错误
  4. 沙箱内代码冲突:测试文件中自行定义hook函数并调用,会被主程序钩子拦截

修正后的主代码

local debug = require "debug"

-- CPU步数限制
local steplimit = 1000
local count = 0

-- 授权函数表:存储函数对象而非名称
local validfunc = {}

-- 提前授权必要的全局安全函数
validfunc[print] = true

-- 钩子函数:检查调用权限
local function hook(event)
    local info
    if event == "call" then
        info = debug.getinfo(2, "fn")
        local func = info.func
        -- 检查是否已授权,或属于沙箱环境函数
        if not validfunc[func] then
            local funcEnv = debug.getinfo(2, "f").env
            if funcEnv ~= chunkEnv then
                error("调用未授权函数: " .. (info.name or "匿名函数"))
            end
            -- 自动授权沙箱内定义的函数
            validfunc[func] = true
        end
    end
    count = count + 1
    if count > steplimit then
        error("脚本CPU占用超限")
    end
    -- 避免info为nil时的打印错误
    if info then
        print(string.format('函数名:%s, 当前步数:%d', info.name or '匿名函数', count))
    end
end

-- 加载沙箱脚本
local chunkEnv = setmetatable({}, { __index = _G })
local f, errorMsg = loadfile("test_lua_exercise_25_8.lua", "t", chunkEnv)
if not f then
    error("加载脚本失败: " .. errorMsg)
end

-- 设置钩子
debug.sethook(hook, "c", 100)

-- 运行沙箱(用pcall捕获错误便于调试)
local success, err = pcall(f)
if not success then
    print("沙箱运行错误:", err)
end

-- 关闭钩子
debug.sethook()

-- 打印已授权函数
print("\n已授权函数列表:")
for func, _ in pairs(validfunc) do
    local info = debug.getinfo(func, "fn")
    print(info.name or "匿名函数", func)
end

修正后的沙箱测试代码(test_lua_exercise_25_8.lua)

-- 定义沙箱内的自定义函数
local function testFunc()
    print("沙箱内testFunc被调用")
end

-- 调用自定义函数
testFunc()

-- 递归调用测试
local count = 0
local function loopFunc()
    count = count + 1
    print("循环次数:", count)
    if count < 5 then
        loopFunc()
    end
end

loopFunc()

关键修复说明

  • 匹配授权逻辑:validfunc改为存储函数对象,与钩子中debug.getinfo返回的func直接匹配
  • 动态授权沙箱函数:钩子中检查函数的环境,若属于沙箱的chunkEnv则自动加入授权表,无需提前收集
  • 修复变量作用域:统一info变量的作用域,避免打印时出现nil错误
  • 提前授权全局函数:将print等必要全局函数加入授权表,防止沙箱内调用被拦截
  • 错误捕获:用pcall包裹沙箱运行,便于调试错误

内容的提问来源于stack exchange,提问作者kos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:03:17