injectcode.lua 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. local debug = debug
  2. local table = table
  3. local FUNC_TEMP=[[
  4. local $ARGS
  5. return function(...)
  6. $SOURCE
  7. end,
  8. function()
  9. return {$LOCALS}
  10. end
  11. ]]
  12. local temp = {}
  13. local function wrap_locals(co, source, level, ext_funcs)
  14. if co == coroutine.running() then
  15. level = level + 3
  16. end
  17. local f = debug.getinfo(co, level,"f").func
  18. if f == nil then
  19. return false, "Invalid level"
  20. end
  21. local uv = {}
  22. local locals = {}
  23. local uv_id = {}
  24. local local_id = {}
  25. if ext_funcs then
  26. for k,v in pairs(ext_funcs) do
  27. table.insert(uv, k)
  28. end
  29. end
  30. local i = 1
  31. while true do
  32. local name, value = debug.getlocal(co, level, i)
  33. if name == nil then
  34. break
  35. end
  36. if name:byte() ~= 40 then -- '('
  37. table.insert(uv, name)
  38. table.insert(locals, ("[%d]=%s,"):format(i,name))
  39. local_id[name] = value
  40. end
  41. i = i + 1
  42. end
  43. local i = 1
  44. while true do
  45. local name = debug.getupvalue(f, i)
  46. if name == nil then
  47. break
  48. end
  49. uv_id[name] = i
  50. table.insert(uv, name)
  51. i = i + 1
  52. end
  53. temp.ARGS = table.concat(uv, ",")
  54. temp.SOURCE = source
  55. temp.LOCALS = table.concat(locals)
  56. local full_source = FUNC_TEMP:gsub("%$(%w+)",temp)
  57. local loader, err = load(full_source, "=(debug)")
  58. if loader == nil then
  59. return false, err
  60. end
  61. local func, update = loader()
  62. -- join func's upvalues
  63. local i = 1
  64. while true do
  65. local name = debug.getupvalue(func, i)
  66. if name == nil then
  67. break
  68. end
  69. if ext_funcs then
  70. local v = ext_funcs[name]
  71. if v then
  72. debug.setupvalue(func, i, v)
  73. end
  74. end
  75. local local_value = local_id[name]
  76. if local_value then
  77. debug.setupvalue(func, i, local_value)
  78. end
  79. local upvalue_id = uv_id[name]
  80. if upvalue_id then
  81. debug.upvaluejoin(func, i, f, upvalue_id)
  82. end
  83. i=i+1
  84. end
  85. local vararg, v = debug.getlocal(co, level, -1)
  86. if vararg then
  87. local vargs = { v }
  88. local i = 2
  89. while true do
  90. local vararg,v = debug.getlocal(co, level, -i)
  91. if vararg then
  92. vargs[i] = v
  93. else
  94. break
  95. end
  96. i=i+1
  97. end
  98. return func, update, table.unpack(vargs)
  99. else
  100. return func, update
  101. end
  102. end
  103. local function exec(co, level, func, update, ...)
  104. if not func then
  105. return false, update
  106. end
  107. if co == coroutine.running() then
  108. level = level + 2
  109. end
  110. local rets = table.pack(pcall(func, ...))
  111. if rets[1] then
  112. local needupdate = update()
  113. for k,v in pairs(needupdate) do
  114. debug.setlocal(co, level,k,v)
  115. end
  116. return table.unpack(rets, 1, rets.n)
  117. else
  118. return false, rets[2]
  119. end
  120. end
  121. return function (source, co, level, ext_funcs)
  122. co = co or coroutine.running()
  123. level = level or 0
  124. return exec(co, level, wrap_locals(co, source, level, ext_funcs))
  125. end