mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 21:33:46 +03:00
360 lines
8.0 KiB
Lua
360 lines
8.0 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
--[[
|
|
luadata by CapsAdmin (fuck copyright, do what you want with this)
|
|
|
|
-- encodes table to string
|
|
string luadata.Encode(tbl)
|
|
|
|
-- decodes string to table
|
|
-- it will throw an error if there's a syntax error in the table
|
|
table luadata.Decode(str)
|
|
|
|
-- writes the table to file ( it's just "file.Write(path, luadata.Encode(str))" )
|
|
nil luadata.WriteFile(path, tbl)
|
|
table luadata.ReadFile(path)
|
|
|
|
-- returns a string of how the variable is typically initialized
|
|
string luadata.ToString(var)
|
|
|
|
-- will let you add your own tostring function for a custom type
|
|
-- if you have made a custom data object, you can do this "mymatrix.LuaDataType = "Matrix33""
|
|
-- and it will make luadata.Type return that instead
|
|
nil luadata.SetModifier(type, callback)
|
|
|
|
]]
|
|
|
|
--- luajit bytecode firewall --
|
|
local opcode_checker
|
|
do
|
|
local bcnames
|
|
|
|
local jit = jit or require("jit")
|
|
local ver = jit and jit.version_num or 0
|
|
|
|
-- what are these magic versions?
|
|
if ver >= 20000 and ver <= 20009 then
|
|
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"
|
|
elseif ver==20100 then -- LuaJIT 2.1.0-beta3
|
|
bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF ISTYPEISNUM 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 TGETR TSETV TSETS TSETB TSETM TSETR CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW"
|
|
end
|
|
|
|
local jutil = jit.util
|
|
if not jutil then
|
|
local ok, _jutil = pcall(require,'jit.util')
|
|
if not ok then
|
|
bcnames = nil
|
|
else
|
|
jutil = _jutil
|
|
end
|
|
end
|
|
|
|
if not bcnames then
|
|
if not jutil then
|
|
print("[luadata] Verifier could not be loaded. luadata may cause infinite loops.")
|
|
else
|
|
ErrorNoHalt"LUADATA SECURITY WARNING: Unable to load verifier, update me!\n"
|
|
end
|
|
opcode_checker = function() return function() return true end end
|
|
else
|
|
local band = bit.band
|
|
|
|
local opcodes = {}
|
|
|
|
--extract opcode names
|
|
for str in bcnames:gmatch "......" do
|
|
str = str:gsub("%s", "")
|
|
table.insert(opcodes, str)
|
|
end
|
|
|
|
local function getopnum(opname)
|
|
for k, v in next, opcodes do
|
|
if v == opname then
|
|
return k
|
|
end
|
|
|
|
end
|
|
|
|
error("not found: " .. opname)
|
|
end
|
|
|
|
|
|
local function getop(func, pc)
|
|
local ins = jutil.funcbc(func, pc)
|
|
return ins and (band(ins, 0xff)+1)
|
|
end
|
|
|
|
|
|
opcode_checker = function(white)
|
|
|
|
local opwhite = {}
|
|
for i=0,#opcodes do table.insert(opwhite, false) end
|
|
|
|
|
|
local function iswhitelisted(opnum)
|
|
local ret = opwhite[opnum]
|
|
if ret == nil then
|
|
error("opcode not found " .. opnum)
|
|
end
|
|
|
|
return ret
|
|
end
|
|
|
|
local function add_whitelist(num)
|
|
if opwhite[num] == nil then
|
|
error "invalid opcode num"
|
|
end
|
|
|
|
opwhite[num] = 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: "..opcodes[ret]
|
|
end
|
|
|
|
end
|
|
return false,"checked max_opcodes"
|
|
end
|
|
|
|
return checker_function
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
local whitelist = [[TNEW
|
|
TDUP
|
|
|
|
TSETV
|
|
TSETS
|
|
TSETB
|
|
TSETM
|
|
|
|
KSTR
|
|
KCDATA
|
|
KSHORT
|
|
KNUM
|
|
KPRI
|
|
KNIL
|
|
|
|
UNM
|
|
|
|
GGET
|
|
CALL
|
|
RET1]]
|
|
|
|
local is_func_ok = opcode_checker(whitelist)
|
|
|
|
-------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local luadata = {}
|
|
local s = luadata
|
|
luadata.is_func_ok = is_func_ok
|
|
|
|
luadata.EscapeSequences = {
|
|
[("\a"):byte()] = [[\a]],
|
|
[("\b"):byte()] = [[\b]],
|
|
[("\f"):byte()] = [[\f]],
|
|
[("\t"):byte()] = [[\t]],
|
|
[("\r"):byte()] = [[\r]],
|
|
[("\v"):byte()] = [[\v]],
|
|
}
|
|
|
|
local tab = 0
|
|
|
|
luadata.Types = {
|
|
["number"] = function(var)
|
|
return ("%s"):format(var)
|
|
end,
|
|
["string"] = function(var)
|
|
return ("%q"):format(var)
|
|
end,
|
|
["boolean"] = function(var)
|
|
return ("%s"):format(var and "true" or "false")
|
|
end,
|
|
["Vector"] = function(var)
|
|
return ("Vector(%s, %s, %s)"):format(var.x, var.y, var.z)
|
|
end,
|
|
["Angle"] = function(var)
|
|
return ("Angle(%s, %s, %s)"):format(var.p, var.y, var.r)
|
|
end,
|
|
["table"] = function(var)
|
|
if
|
|
isnumber(var.r) and
|
|
isnumber(var.g) and
|
|
isnumber(var.b) and
|
|
isnumber(var.a)
|
|
then
|
|
return ("Color(%s, %s, %s, %s)"):format(var.r, var.g, var.b, var.a)
|
|
end
|
|
|
|
tab = tab + 1
|
|
local str = luadata.Encode(var, true)
|
|
tab = tab - 1
|
|
return str
|
|
end,
|
|
}
|
|
|
|
function luadata.SetModifier(type, callback)
|
|
luadata.Types[type] = callback
|
|
end
|
|
|
|
function luadata.Type(var)
|
|
local t
|
|
|
|
if IsEntity(var) then
|
|
if var:IsValid() then
|
|
t = "Entity"
|
|
else
|
|
t = "NULL"
|
|
end
|
|
else
|
|
t = type(var)
|
|
end
|
|
|
|
if t == "table" then
|
|
if var.LuaDataType then
|
|
t = var.LuaDataType
|
|
end
|
|
end
|
|
|
|
return t
|
|
end
|
|
|
|
function luadata.ToString(var)
|
|
local func = s.Types[s.Type(var)]
|
|
return func and func(var)
|
|
end
|
|
|
|
function luadata.Encode(tbl, __brackets)
|
|
if luadata.Hushed then return end
|
|
|
|
local str = __brackets and "{\n" or ""
|
|
|
|
for key, value in pairs(tbl) do
|
|
value = s.ToString(value)
|
|
key = s.ToString(key)
|
|
|
|
if key and value and key ~= "__index" then
|
|
str = str .. ("\t"):rep(tab) .. ("[%s] = %s,\n"):format(key, value)
|
|
end
|
|
end
|
|
|
|
str = str .. ("\t"):rep(tab-1) .. (__brackets and "}" or "")
|
|
|
|
return str
|
|
end
|
|
|
|
local env = {
|
|
Vector=Vector,
|
|
Angle=Angle,
|
|
Color=Color,
|
|
--Entity=Entity,
|
|
}
|
|
|
|
-- TODO: Bytecode analysis for bad loop and string functions?
|
|
function luadata.Decode(str,nojail)
|
|
local func = CompileString(string.format("return { %s }",str), "luadata_decode", false)
|
|
|
|
if isstring(func) then
|
|
--ErrorNoHalt("Luadata decode syntax: "..tostring(func):gsub("^luadata_decode","")..'\n')
|
|
|
|
return nil,func
|
|
end
|
|
|
|
if not nojail then
|
|
setfenv(func,env)
|
|
elseif istable(nojail) then
|
|
setfenv(func,nojail)
|
|
elseif isfunction(nojail) then
|
|
nojail( func )
|
|
end
|
|
|
|
|
|
local ok,err = is_func_ok( func )
|
|
if not ok or err then
|
|
err = err or "invalid opcodes detected"
|
|
--ErrorNoHalt("Luadata opcode: "..tostring(err):gsub("^luadata_decode","")..'\n')
|
|
|
|
return nil,err
|
|
end
|
|
|
|
local ok, err = xpcall(func,debug.traceback)
|
|
|
|
if not ok then
|
|
--ErrorNoHalt("Luadata decode: "..tostring(err):gsub("^luadata_decode","")..'\n')
|
|
|
|
return nil,err
|
|
end
|
|
|
|
if isfunction(nojail) then
|
|
nojail( func, err )
|
|
end
|
|
|
|
return err
|
|
end
|
|
|
|
do -- file extension
|
|
function luadata.WriteFile(path, tbl)
|
|
if tbl==nil or false --[[empty table!?]] then
|
|
if file.Exists(path,'DATA') then
|
|
file.Delete(path,'DATA')
|
|
return true
|
|
end
|
|
return false,"file does not exist"
|
|
end
|
|
local encoded = luadata.Encode(tbl)
|
|
file.Write(path, encoded)
|
|
--if not file.Exists(path,'DATA') then return false,"could not write" end
|
|
return encoded
|
|
end
|
|
|
|
function luadata.ReadFile(path,location,noinvalid)
|
|
local file = file.Read(path,location or 'DATA')
|
|
if not file then
|
|
if noinvalid then return end
|
|
return false,"invalid file"
|
|
end
|
|
return luadata.Decode(file)
|
|
end
|
|
end
|
|
|
|
return luadata
|