Last active
February 8, 2022 06:16
-
-
Save hangj/3e94c3894cb1530112bc9fa9f6da1fb5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
不同于 cloudwu 的实现方式,我用的是 metatable
https://github.com/cloudwu/skynet/blob/master/lualib/skynet/injectcode.lua