Skip to content

Instantly share code, notes, and snippets.

@hangj
Last active February 8, 2022 06:16
Show Gist options
  • Save hangj/3e94c3894cb1530112bc9fa9f6da1fb5 to your computer and use it in GitHub Desktop.
Save hangj/3e94c3894cb1530112bc9fa9f6da1fb5 to your computer and use it in GitHub Desktop.
local function run(src, level)
local level = level or 1
level = level + 3
assert(level >= 3)
local function get(t, k)
-- print('get:', k)
-- print('bt:', debug.traceback())
local level = level + 1
local info = debug.getinfo(level, 'flnStuL')
-- print(info.name)
if info then
local f = info.func
local i = 1
while true do
local name, value = debug.getlocal(level, i)
if not name then break end
-- print('level,name,value:', level, name, value)
-- if name:byte() ~= 40 then -- '('
if name == k then
-- debug.setlocal(level, name, value)
return value
end
i = i + 1
end
local i = 1
while true do
local name, value = debug.getupvalue(f, i)
if not name then break end
if name == k then
return value
end
i = i + 1
end
end
return _G[k]
end
local function set(t, k, v)
-- print('set:', t, k, v)
local level = level + 1
local info = debug.getinfo(level, 'flnStuL')
if info then
local f = info.func
local i = 1
while true do
local name, value = debug.getlocal(level, i)
if not name then break end
-- if name:byte() ~= 40 then -- '('
if name == k then
debug.setlocal(level, i, v)
return
end
i = i + 1
end
local i = 1
while true do
local name, value = debug.getupvalue(f, i)
if not name then break end
if name == k then
debug.setupvalue(f, i, v)
return
end
i = i + 1
end
end
if _G[k] then
_G[k] = v
return
end
-- if not find a local value or upvalue or global value, then raise an error
error("can not set ".. k) -- rawset(t, k, v)
end
local env = setmetatable({}, {__index = get, __newindex = set})
local vargs = {} -- ...
local info = debug.getinfo(level, 'flnStuL')
if info then
local i = 1
while true do
local vararg, value = debug.getlocal(level, -i)
if not vararg then break end
vargs[i] = value
i = i + 1
end
end
local func = load(src, "@hangj_inject", 'bt', env)
if not func then return end
local rets = table.pack(pcall(func, table.unpack(vargs)))
if rets[1] then
return table.unpack(rets, 1, rets.n)
end
end
return run
local inject = require('inject')
local g_a = 'g_a'
local function foo()
print('foo')
end
local function fuck(...)
local a = 'aaaa'
print('a_before:', a)
inject [[
print('vargs:', ...)
local lo = 'lo'
lo = 'ol'
a = 'bbb'
g_a = 'gg_bb'
print("fuck:", a, lo, g_a)
foo()
foo = function() print(g_a) end
return 'hello world'
]]
print('a_after:', a)
print('g_a:', g_a)
end
fuck(6,7,8)
foo()
@hangj
Copy link
Author

hangj commented Jan 27, 2022

不同于 cloudwu 的实现方式,我用的是 metatable
https://github.com/cloudwu/skynet/blob/master/lualib/skynet/injectcode.lua

@hangj
Copy link
Author

hangj commented Jan 27, 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment