fix(config): 优化配置解析

- 完善 `FromLua` 转换与边界校验,拦截空洞 (`nil`) 及非整数键
This commit is contained in:
2026-08-19 11:34:16 +08:00
parent e3cb065b35
commit f59040c11e
7 changed files with 168 additions and 167 deletions

View File

@@ -1,5 +1,5 @@
use crate::error::ShimError;
use crate::{ShimConfig, ShimLayout};
use anyhow::{Context, Result, anyhow, bail};
use mlua::{FromLua, Lua, StdLib, Table, Value};
use std::ffi::OsStr;
use std::path::Path;
@@ -17,13 +17,13 @@ pub struct LuaRuntime {
impl LuaRuntime {
/// 初始化限定权限的 Lua 沙箱环境
pub fn new(layout: &ShimLayout) -> Result<Self, ShimError> {
pub fn new(layout: &ShimLayout) -> Result<Self> {
// 只加载安全的标准库,剥离 os / io 等风险模块
let lua = Lua::new_with(
StdLib::TABLE | StdLib::STRING | StdLib::MATH | StdLib::PACKAGE,
mlua::LuaOptions::default(),
)
.map_err(|e| ShimError::Environment(format!("初始化 Lua 失败: {}", e)))?;
.context("初始化 Lua 失败")?;
let globals = lua.globals();
@@ -34,7 +34,7 @@ impl LuaRuntime {
// 1. 注入锚点变量 __SHIM_DIR__shim 安装根目录)
globals
.set("__SHIM_DIR__", root_dir.clone())
.map_err(|e| ShimError::Environment(e.to_string()))?;
.context("设置 __SHIM_DIR__ 环境变量失败")?;
// 2. 安全暴露 get_env 供配置读取环境变量
// 返回按平台路径分隔符拆分后的段数组(自动剥离引号包裹),
@@ -68,11 +68,11 @@ impl LuaRuntime {
Ok(table)
})
.map_err(|e| ShimError::Environment(e.to_string()))?;
.context("注册 get_env 函数失败")?;
globals
.set("get_env", get_env)
.map_err(|e| ShimError::Environment(e.to_string()))?;
.context("挂载 get_env 全局函数失败")?;
// 3. 配置 package.path确保 require 行为正常
if let Ok(package) = globals.get::<Table>("package") {
@@ -92,10 +92,10 @@ impl LuaRuntime {
// 而不是让整个 shims.lua 解析失败(排查问题时日志可见)
let original_require: mlua::Function = globals
.get("require")
.map_err(|e| ShimError::Environment(format!("获取 require 失败: {}", e)))?;
.context("获取内置 require 函数失败")?;
globals
.set("_rshim_original_require", &original_require)
.map_err(|e| ShimError::Environment(e.to_string()))?;
.context("备份原始 require 函数失败")?;
let wrapped_require = lua
.create_function(|lua, module: String| -> mlua::Result<Value> {
@@ -112,26 +112,27 @@ impl LuaRuntime {
}
}
})
.map_err(|e| ShimError::Environment(e.to_string()))?;
.context("创建包装版 require 函数失败")?;
globals
.set("require", wrapped_require)
.map_err(|e| ShimError::Environment(e.to_string()))?;
.context("重载 require 函数失败")?;
Ok(Self { lua })
}
/// 执行指定脚本文件,直接返回完整的 Lua Table
pub fn eval_script<T: FromLua>(&self, path: impl AsRef<Path>) -> Result<T, ShimError> {
pub fn eval_script<T: FromLua>(&self, path: impl AsRef<Path>) -> Result<T> {
let path = path.as_ref();
// println!("path {:?}", path);
let bytes = fs::read(path)?;
let code = String::from_utf8(bytes).map_err(|e| {
ShimError::InvalidConfig(format!(
"{} 不是有效的 UTF-8 文件(请将 Lua 配置文件保存为 UTF-8 编码): {}",
path.display(),
e.utf8_error()
))
let bytes =
fs::read(path).with_context(|| format!("无法读取配置文件: {}", path.display()))?;
let code = String::from_utf8(bytes).with_context(|| {
format!(
"{} 不是有效的 UTF-8 文件(请将 Lua 配置文件保存为 UTF-8 编码)",
path.display()
)
})?;
println!("code {:?}", code);
let chunk_name = format!("@{}", path.display());
@@ -140,15 +141,13 @@ impl LuaRuntime {
.load(&code)
.set_name(&chunk_name)
.eval::<T>()
.map_err(|e| ShimError::LuaExecution {
file: path.display().to_string(),
source: e,
})
// .map_err(|e| anyhow!(e.to_string()))
.with_context(|| format!("执行 Lua 配置文件失败: {}", path.display()))
}
// /// 将 Lua Value 解析转化为 ShimConfig 数据对象
// pub fn parse_config(&self, value: Value) -> Result<ShimConfig, ShimError> {
// ShimConfig::from_lua(value, &self.lua).map_err(|e| ShimError::InvalidConfig(e.to_string()))
// pub fn parse_config(&self, value: Value) -> Result<ShimConfig, Error> {
// ShimConfig::from_lua(value, &self.lua).map_err(|e| Error::InvalidConfig(e.to_string()))
// }
}