Created
July 28, 2014 09:24
-
-
Save Python1320/6a1a789f8031a6c4c464 to your computer and use it in GitHub Desktop.
luajit opcode whitelist for Garry's Mod
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 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