Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ require (
github.com/tree-sitter/tree-sitter-php v0.24.2
github.com/tree-sitter/tree-sitter-python v0.25.0
github.com/tree-sitter/tree-sitter-typescript v0.23.2
github.com/wippyai/go-lua v1.5.16
github.com/wippyai/go-lua v1.5.17-0.20260707180131-68784b1e34c8
github.com/wippyai/module-registry-proto-go v0.0.1
github.com/wippyai/tree-sitter-markdown v0.0.3
github.com/wippyai/tree-sitter-sql v0.0.4
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -576,8 +576,8 @@ github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/wippyai/go-lua v1.5.16 h1:FOjZfd3H73MLQY0/nnKKW4Fik/rZDgCcg0L3W0Yr6Iw=
github.com/wippyai/go-lua v1.5.16/go.mod h1:cwD+390gJgx9cs+Zamby/lch5csqPV9RN1aDEfx/27M=
github.com/wippyai/go-lua v1.5.17-0.20260707180131-68784b1e34c8 h1:mlOaUK32iUOUxwDxn6qo4vFUBFVNyYp3tZN4JsqI0u0=
github.com/wippyai/go-lua v1.5.17-0.20260707180131-68784b1e34c8/go.mod h1:cwD+390gJgx9cs+Zamby/lch5csqPV9RN1aDEfx/27M=
github.com/wippyai/module-registry-proto-go v0.0.1 h1:EYnW8MTrI/gs7TJ0ilTVgJal3e0NWmXQigeamrXu0mk=
github.com/wippyai/module-registry-proto-go v0.0.1/go.mod h1:p4ihYQKRQuqRVLxaH1YL0IEnkz4zKdyfVADOwvA5Tno=
github.com/wippyai/tree-sitter-markdown v0.0.3 h1:u6e53+hzPSS848Xhm+I48SwtvWQHrC21wDrogdwCwuc=
Expand Down
9 changes: 9 additions & 0 deletions runtime/lua/engine/cached_libs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var (
cachedCoroutineLib *lua.LTable
cachedStringLib *lua.LTable
cachedErrorsLib *lua.LTable
cachedDebugLib *lua.LTable

// cachedLibs is the ordered set of standard libraries bound as globals by
// BindCachedLibs. It is the single source for both binding and StdLibNames.
Expand Down Expand Up @@ -58,13 +59,21 @@ func initCachedLibs() {
cachedErrorsLib = tmp.GetGlobal(lua.ErrorsLibName).(*lua.LTable)
cachedErrorsLib.Immutable = true

lua.OpenDebug(tmp)
cachedDebugLib = tmp.GetGlobal(lua.DebugLibName).(*lua.LTable)
for _, fn := range []string{"setlocal", "setmetatable", "setupvalue", "getmetatable"} {
cachedDebugLib.RawSetString(fn, lua.LNil)
}
cachedDebugLib.Immutable = true

cachedLibs = []cachedLib{
{name: lua.TabLibName, tbl: cachedTableLib},
{name: lua.MathLibName, tbl: cachedMathLib},
{name: "os", tbl: cachedOsLib},
{name: lua.CoroutineLibName, tbl: cachedCoroutineLib},
{name: lua.StringLibName, tbl: cachedStringLib},
{name: lua.ErrorsLibName, tbl: cachedErrorsLib},
{name: lua.DebugLibName, tbl: cachedDebugLib},
}
})
}
Expand Down
89 changes: 89 additions & 0 deletions runtime/lua/engine/cached_libs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,94 @@ func TestBindCachedLibs_ErrorsLib(t *testing.T) {
`))
}

func TestBindCachedLibs_DebugLib_Present(t *testing.T) {
l := lua.NewState(lua.Options{SkipOpenLibs: true})
defer l.Close()
lua.OpenBase(l)
BindCachedLibs(l)

require.NoError(t, l.DoString(`
assert(type(debug) == "table")
`))
}

func TestBindCachedLibs_DebugLib_HasSafeFuncs(t *testing.T) {
l := lua.NewState(lua.Options{SkipOpenLibs: true})
defer l.Close()
lua.OpenBase(l)
BindCachedLibs(l)

for _, fn := range []string{"traceback", "getinfo", "getlocal", "getupvalue"} {
err := l.DoString(`assert(type(debug.` + fn + `) == "function", "debug.` + fn + ` must be a function")`)
require.NoError(t, err, "debug.%s must be exposed", fn)
}
}

func TestBindCachedLibs_DebugLib_MissingUnsafeFuncs(t *testing.T) {
l := lua.NewState(lua.Options{SkipOpenLibs: true})
defer l.Close()
lua.OpenBase(l)
BindCachedLibs(l)

for _, fn := range []string{"setlocal", "setmetatable", "setupvalue", "getmetatable"} {
err := l.DoString(`assert(debug.` + fn + ` == nil, "debug.` + fn + ` must be absent")`)
require.NoError(t, err, "debug.%s must NOT be exposed", fn)
}
}

func TestBindCachedLibs_DebugLib_Immutable(t *testing.T) {
l := lua.NewState(lua.Options{SkipOpenLibs: true})
defer l.Close()
lua.OpenBase(l)
BindCachedLibs(l)

setErr := l.DoString(`
local ok, err = pcall(function()
debug.setlocal = function() end
end)
assert(not ok, "mutating the immutable debug table must fail")
`)
require.NoError(t, setErr, "mutating debug table must error, not crash")

getErr := l.DoString(`assert(debug.setlocal == nil, "setlocal must remain nil")`)
require.NoError(t, getErr)
}

func TestBindCachedLibs_DebugLib_GetInfoWorks(t *testing.T) {
l := lua.NewState(lua.Options{SkipOpenLibs: true})
defer l.Close()
lua.OpenBase(l)
BindCachedLibs(l)

err := l.DoString(`
local function sample() return debug.getinfo(1) end
local info = sample()
assert(type(info) == "table")
assert(type(info.currentline) == "number")
assert(type(info.source) == "string")
assert(info.name == "sample")
`)
require.NoError(t, err)
}

func TestBindCachedLibs_DebugLib_GetLocalWorks(t *testing.T) {
l := lua.NewState(lua.Options{SkipOpenLibs: true})
defer l.Close()
lua.OpenBase(l)
BindCachedLibs(l)

err := l.DoString(`
local function sample()
local captured = "value-here"
local name, value = debug.getlocal(1, 1)
assert(name == "captured", "first local name should be 'captured'")
assert(value == "value-here", "first local value should be 'value-here'")
end
sample()
`)
require.NoError(t, err)
}

func TestBindCachedLibs_MultipleStates(t *testing.T) {
states := make([]*lua.LState, 3)
for i := range states {
Expand Down Expand Up @@ -123,4 +211,5 @@ func TestBindCachedLibs_Immutable(t *testing.T) {
assert.True(t, cachedCoroutineLib.Immutable)
assert.True(t, cachedStringLib.Immutable)
assert.True(t, cachedErrorsLib.Immutable)
assert.True(t, cachedDebugLib.Immutable)
}
2 changes: 2 additions & 0 deletions runtime/lua/engine/core_modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/wippyai/runtime/runtime/lua/engine/value"
"github.com/wippyai/runtime/runtime/lua/modules/ostime"
"github.com/wippyai/runtime/runtime/lua/modules/payload"
"github.com/wippyai/runtime/runtime/lua/modules/traceback"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -104,6 +105,7 @@ func printFunc(l *lua.LState) int {
var coreModules = []*luaapi.ModuleDef{
payload.Module,
ostime.Module,
traceback.Module,
PrintModule,
ChannelModule,
}
Expand Down
Loading