Skip to content

Instantly share code, notes, and snippets.

@Python1320
Created July 28, 2014 09:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Python1320/6a1a789f8031a6c4c464 to your computer and use it in GitHub Desktop.
Save Python1320/6a1a789f8031a6c4c464 to your computer and use it in GitHub Desktop.
luajit opcode whitelist for Garry's Mod
local bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TSETV TSETS TSETB TSETM CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW"
local jit = jit or require("jit")
assert(jit.version_num == 20003, "LuaJIT version mismatch")
local jutil = jit.util or require'jit.util'
local band = bit.band
local t = {}
--extract opcode names
for str in bcnames:gmatch "......" do
str = str:gsub(" +$", "")
table.insert(t, str)
end
local function opname(op)
return t[op + 1]
end
local function getopnum(opname)
for k, v in next, t do
if v == opname then
return k - 1
end
end
error("not found: " .. opname)
end
local function getop(func, pc)
local ins = jutil.funcbc(func, pc)
return ins and band(ins, 0xff)
end
local function opcode_checker(white)
local opwhite = {}
for i=0,#t do table.insert(opwhite, false) end
local function iswhitelisted(opnum)
local ret = opwhite[opnum + 1]
if ret == nil then
error("opcode not found " .. opnum)
end
return ret
end
local function add_whitelist(num)
if opwhite[num + 1] == nil then
error "invalid opcode num"
end
opwhite[num + 1] = true
end
for line in white:gmatch '[^\r\n]+' do
local opstr_towhite = line:match '[%w]+'
if opstr_towhite and opstr_towhite:len() > 0 then
local whiteopnum = getopnum(opstr_towhite)
add_whitelist(whiteopnum)
assert(iswhitelisted(whiteopnum))
end
end
local function checker_function(func,max_opcodes)
max_opcodes = max_opcodes or math.huge
for i = 1, max_opcodes do
local ret = getop(func, i)
if not ret then
return true
end
if not iswhitelisted(ret) then
--error("non-whitelisted: " .. )
return false,"non-whitelisted: "..opname(ret)
end
end
return false,"checked max_opcodes"
end
return checker_function
end
local white = [[TNEW
TDUP
TSETV
TSETS
TSETB
TSETM
KSTR
KCDATA
KSHORT
KNUM
KPRI
KNIL
GGET
CALL
RET1]]
local isok = opcode_checker(white)
local function FUNC1()
return { Vector(0, 0, 0), { Angle() } }
end
local function FUNC2()
return { Vector(0, 0, 0), { Angle() } },(function()end)()
end
print("ISOK1",isok(FUNC1))
print("ISOK2",isok(FUNC2))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment