mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-10-14 18:19:30 +03:00
luar: whitelist
This commit is contained in:
@@ -45,7 +45,7 @@ func RegisterLua(L *lua.LState) {
|
||||
"AnyMatch": luaIPAnyMatch,
|
||||
"Matches": luaIPMatches,
|
||||
"FilterIPs": newLuaIPFilterIPs(xlua.NewSlicePusher[net.IP](L)),
|
||||
})
|
||||
}, "SetReverse", "ToggleReverse")
|
||||
return 1
|
||||
}))
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ local geodata = require("xray.geodata")
|
||||
local matcher = geodata.BuildIPMatcher("127.0.0.0/8")
|
||||
assert(matcher.Match == matcher.match and matcher.AnyMatch == matcher.anyMatch)
|
||||
assert(matcher.Matches == matcher.matches and matcher.FilterIPs == matcher.filterIPs)
|
||||
assert(matcher.Reload == nil and matcher.reload == nil)
|
||||
assert(matcher:match(ip))
|
||||
assert(matcher:anyMatch({ip}) and matcher:matches({ip}))
|
||||
assert(not matcher:AnyMatch(nil))
|
||||
@@ -97,6 +98,11 @@ assert(matcher.missing == nil)
|
||||
|
||||
local domain = geodata.BuildDomainMatcher("full:example.com")
|
||||
assert(domain.Match == domain.match and domain.MatchAny == domain.matchAny)
|
||||
assert(domain.Reload == nil and domain.reload == nil)
|
||||
for _, value in ipairs({matcher, domain}) do
|
||||
assert(not pcall(function() return -value end))
|
||||
assert(not pcall(function() return value ^ {} end))
|
||||
end
|
||||
assert(domain:matchAny("example.com"))
|
||||
assert(#domain:Match("example.com") == 1)
|
||||
assert(domain:match("example.com")[1] == 0)
|
||||
|
||||
+28
-3
@@ -27,16 +27,37 @@ func NewSlicePusher[T any](L *glua.LState) func(*glua.LState, []T) {
|
||||
// it must leave the stack unchanged for the original luar wrapper.
|
||||
type DirectMethod func(L *glua.LState) (nresults int, handled bool)
|
||||
|
||||
// PushMethods pushes a luar userdata exposing only the named Go methods and
|
||||
// their aliases through reflected calls. The method list is fixed by the first
|
||||
// binding of that Go type in each LState.
|
||||
func PushMethods(L *glua.LState, value any, methods ...string) {
|
||||
PushWithDirectMethods(L, value, nil, methods...)
|
||||
}
|
||||
|
||||
// PushWithDirectMethods pushes a luar userdata with typed Go method bindings.
|
||||
// Handled calls bypass luar's argument conversion and reflect.Call; method lookup
|
||||
// uses the methods table directly instead of luar's reflected __index handler.
|
||||
// value must expose methods only. Bindings and their closures are installed once
|
||||
// per Go type per LState, outside the method-call hot path.
|
||||
func PushWithDirectMethods(L *glua.LState, value any, directMethods map[string]DirectMethod) {
|
||||
// Only directMethods and additionalMethods are exposed, including their aliases.
|
||||
// Bindings and their closures are installed once per Go type per LState, outside
|
||||
// the method-call hot path.
|
||||
func PushWithDirectMethods(L *glua.LState, value any, directMethods map[string]DirectMethod, additionalMethods ...string) {
|
||||
userdata := luar.New(L, value).(*glua.LUserData)
|
||||
metatable := userdata.Metatable.(*glua.LTable)
|
||||
methods := metatable.RawGetString("methods").(*glua.LTable)
|
||||
if metatable.RawGetString("__index") != methods {
|
||||
// Keep all aliases for the explicitly exposed methods.
|
||||
exposed := make(map[glua.LValue]bool, len(directMethods)+len(additionalMethods))
|
||||
for name := range directMethods {
|
||||
exposed[methods.RawGetString(name)] = true
|
||||
}
|
||||
for _, name := range additionalMethods {
|
||||
exposed[methods.RawGetString(name)] = true
|
||||
}
|
||||
for key, method := methods.Next(glua.LNil); key != glua.LNil; key, method = methods.Next(key) {
|
||||
if !exposed[method] {
|
||||
methods.RawSet(key, glua.LNil)
|
||||
}
|
||||
}
|
||||
for name, direct := range directMethods {
|
||||
original := methods.RawGetString(name)
|
||||
fn := L.NewFunction(func(L *glua.LState) int {
|
||||
@@ -52,6 +73,10 @@ func PushWithDirectMethods(L *glua.LState, value any, directMethods map[string]D
|
||||
}
|
||||
}
|
||||
}
|
||||
// Pointer operations would bypass the method-only API.
|
||||
metatable.RawSetString("__newindex", glua.LNil)
|
||||
metatable.RawSetString("__pow", glua.LNil)
|
||||
metatable.RawSetString("__unm", glua.LNil)
|
||||
metatable.RawSetString("__index", methods)
|
||||
}
|
||||
L.Push(userdata)
|
||||
|
||||
Reference in New Issue
Block a user