mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-14 19:44:02 +00:00
lua: preserve native Stringer and error output in sandbox tostring()
This commit is contained in:
+12
-4
@@ -3,6 +3,7 @@ package lua
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -121,15 +122,22 @@ func newSandboxedState() *glua.LState {
|
|||||||
L.GetGlobal(glua.StringLibName).(*glua.LTable).RawSetString("dump", glua.LNil)
|
L.GetGlobal(glua.StringLibName).(*glua.LTable).RawSetString("dump", glua.LNil)
|
||||||
L.GetGlobal(glua.MathLibName).(*glua.LTable).RawSetString("randomseed", glua.LNil)
|
L.GetGlobal(glua.MathLibName).(*glua.LTable).RawSetString("randomseed", glua.LNil)
|
||||||
|
|
||||||
// Hide object addresses without invoking __tostring.
|
// Preserve native Stringer/error output without using Lua's address-based defaults.
|
||||||
L.SetGlobal("tostring", L.NewFunction(func(L *glua.LState) int {
|
L.SetGlobal("tostring", L.NewFunction(func(L *glua.LState) int {
|
||||||
value := L.CheckAny(1)
|
value := L.CheckAny(1)
|
||||||
|
result := "<opaque>"
|
||||||
switch value.Type() {
|
switch value.Type() {
|
||||||
case glua.LTNil, glua.LTBool, glua.LTNumber, glua.LTString:
|
case glua.LTNil, glua.LTBool, glua.LTNumber, glua.LTString:
|
||||||
L.Push(glua.LString(value.String()))
|
result = value.String()
|
||||||
default:
|
case glua.LTUserData:
|
||||||
L.Push(glua.LString("<opaque>"))
|
switch native := value.(*glua.LUserData).Value.(type) {
|
||||||
|
case fmt.Stringer:
|
||||||
|
result = native.String()
|
||||||
|
case error:
|
||||||
|
result = native.Error()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
L.Push(glua.LString(result))
|
||||||
return 1
|
return 1
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -18,6 +19,7 @@ import (
|
|||||||
"weak"
|
"weak"
|
||||||
|
|
||||||
glua "github.com/yuin/gopher-lua"
|
glua "github.com/yuin/gopher-lua"
|
||||||
|
luar "layeh.com/gopher-luar"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestProgramStatesAreIndependent(t *testing.T) {
|
func TestProgramStatesAreIndependent(t *testing.T) {
|
||||||
@@ -631,7 +633,12 @@ for _, convert in ipairs({tostring, require("_G").tostring}) do
|
|||||||
assert(convert("") == "" and convert("hello") == "hello")
|
assert(convert("") == "" and convert("hello") == "hello")
|
||||||
assert(convert(42, {}) == "42")
|
assert(convert(42, {}) == "42")
|
||||||
assert(not pcall(convert))
|
assert(not pcall(convert))
|
||||||
for _, value in ipairs({{}, function() end, convert, testUserdata, testThread, testChannel}) do
|
assert(convert(testIPv4) == "192.0.2.1")
|
||||||
|
assert(convert(testIPv6) == "2001:db8::1")
|
||||||
|
assert(convert(testNativeIP) == "198.51.100.1")
|
||||||
|
assert(convert(testNativeStringer) == "0xdeadbeef")
|
||||||
|
assert(convert(testNativeError) == "lookup failed")
|
||||||
|
for _, value in ipairs({{}, function() end, convert, testUserdata, testThread, testChannel, testGoStruct, testIPs}) do
|
||||||
local ok, result = pcall(convert, value)
|
local ok, result = pcall(convert, value)
|
||||||
assert(ok and result == "<opaque>")
|
assert(ok and result == "<opaque>")
|
||||||
end
|
end
|
||||||
@@ -642,6 +649,21 @@ string.__tostring = nil
|
|||||||
`)
|
`)
|
||||||
var metamethodCalls int
|
var metamethodCalls int
|
||||||
L, err := program.NewState(context.Background(), func(L *glua.LState) {
|
L, err := program.NewState(context.Background(), func(L *glua.LState) {
|
||||||
|
L.SetGlobal("testIPv4", luar.New(L, net.ParseIP("192.0.2.1")))
|
||||||
|
L.SetGlobal("testIPv6", luar.New(L, net.ParseIP("2001:db8::1")))
|
||||||
|
PushUserData(L, net.ParseIP("198.51.100.1"))
|
||||||
|
L.SetGlobal("testNativeIP", L.Get(-1))
|
||||||
|
L.Pop(1)
|
||||||
|
PushUserData(L, bytes.NewBufferString("0xdeadbeef"))
|
||||||
|
L.SetGlobal("testNativeStringer", L.Get(-1))
|
||||||
|
L.Pop(1)
|
||||||
|
PushError(L, errors.New("lookup failed"))
|
||||||
|
L.SetGlobal("testNativeError", L.Get(-1))
|
||||||
|
L.Pop(1)
|
||||||
|
L.SetGlobal("testGoStruct", luar.New(L, &struct{ Value string }{"readable field"}))
|
||||||
|
NewSlicePusher[net.IP](L)(L, []net.IP{net.ParseIP("192.0.2.1")})
|
||||||
|
L.SetGlobal("testIPs", L.Get(-1))
|
||||||
|
L.Pop(1)
|
||||||
userdata := L.NewUserData()
|
userdata := L.NewUserData()
|
||||||
metatable := L.NewTable()
|
metatable := L.NewTable()
|
||||||
metatable.RawSetString("__tostring", L.NewFunction(func(L *glua.LState) int {
|
metatable.RawSetString("__tostring", L.NewFunction(func(L *glua.LState) int {
|
||||||
|
|||||||
Reference in New Issue
Block a user