a
    TÀÚj«  ã                   @  s‚   d Z ddlmZ ddlZddlZdddœdd„Zdd	dd
œdd„Zdd	ddœdd„Zddœdd„Zdd„ Z	ddd	ddœdd„Z
dS )a'  Build a split-handler VM runtime with lazily decrypted handler closures.

The original VM's dispatch chain is parsed into individual handler bodies.
Each body is wrapped in a function factory, encrypted, and stored in a handler
table.  A handler is decrypted and compiled only on its first use.
é    )ÚannotationsNÚstr)ÚtextÚreturnc                 C  s¼   |   dd¡}dg}|D ]�}|dkr.| d¡ q|dkrB| d¡ qd|  krVd	k s`n |d
krp| d| ¡ qd|  kr„dk r˜n n| t|ƒ¡ q| d| ¡ q| d¡ d |¡S )Núutf-8Úsurrogateescapeú"é\   z\\é"   z\"é
   é   é	   z\%03dé    é   Ú )ÚencodeÚappendÚchrÚjoin)r   ÚdataÚoutÚb© r   ú1/opt/ws-remote/luraph_compiler/handler_runtime.pyÚ
_lua_quote   s    
r   ÚbytesÚint)r   Úseedr   c                 C  sz   |dA d@ }t | ƒ}tt|ƒƒD ]P}||d> d@ A d@ }||d? A d@ }||d> d@ A d@ }||  |d@ N  < q t|ƒS )Nl   ¹yn< ì   ÿÿ r   é   é   éÿ   )Ú	bytearrayÚrangeÚlenr   )r   r   Ústater   Úir   r   r   Ú_stream    s    r'   )Úsourcer   r   c                 C  s   t |  dd¡|ƒ ¡ S )Nr   r   )r'   r   Úhex)r(   r   r   r   r   Ú_encrypt_source+   s    r*   )Úvmc                   s@  |   d¡‰ d }tˆ ƒD ]\}}| d¡r|} q2q|d u rBtdƒ‚d }t|d tˆ ƒƒD ](}ˆ |  d¡sxˆ |  d¡rX|} q‚qX|d u r’tdƒ‚‡ fdd	„t||ƒD ƒ}g }t|ƒD ]„\}}|d t|ƒk rÚ||d  n|}	ˆ | }
d
 ˆ |d |	… ¡}dd	„ t d|
¡D ƒ}|�sq¶t	t 
d|¡ƒ}| |||f¡ q¶|S )NTú
		if op ==zhandler chain not foundé   z		else
z		else zhandler chain end not foundc                   s,   g | ]$}ˆ |   d ¡s$ˆ |   d¡r|‘qS )r,   z		elseif op ==)Ú
startswith)Ú.0r&   ©Úlinesr   r   Ú
<listcomp>?   s   ÿz%_extract_handlers.<locals>.<listcomp>r   c                 S  s   g | ]}t |d ƒ‘qS )r   )r   )r/   Úvr   r   r   r2   F   ó    zop\s*==\s*(0x[0-9A-Fa-f]+|\d+)z(?m)^\s*return\b)Ú
splitlinesÚ	enumerater.   Ú
ValueErrorr#   r$   r   ÚreÚfindallÚboolÚsearchr   )r+   Ústartr&   ÚlineÚelse_atÚstartsÚhandlersÚnÚatÚendÚheaderÚbodyÚopsÚterminalr   r0   r   Ú_extract_handlers/   s6    

 rH   c                   sZ   d}i }t ƒ }|D ]B}dd ‡ fdd„tdƒD ƒ¡ }||vr| |¡ |||< qqq|S )N)ÚctxÚqÚVÚtopÚupsÚvaZnvaÚrbÚKÚpackÚunpackÚcellZcellvalZcellputÚmkclosÚtruthyÚENVÚcallwithZCELL_MTÚpcÚinsÚboxedÚ__r   c                 3  s   | ]}ˆ   d ¡V  qdS )Ú>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789N)Úchoice)r/   Ú_©Úrngr   r   Ú	<genexpr>V   r4   z(_random_handler_names.<locals>.<genexpr>é   )Úsetr   r#   Úadd)r`   Úfieldsr   ÚusedÚoldÚnamer   r_   r   Ú_random_handler_namesN   s     
ri   )r+   Úkeyr   c              	   C  s¢  t | ƒ}t t|ƒd d d@ ¡}g }|D ]Ž\}}}| dd¡}t|ƒ}	|sXd| d n
d| d }
|	 ¡ D ]$\}}t d	t 	|¡ d
 ||
¡}
qlt
|
|ƒ}|D ]}| ||||f¡ q q*tdƒD ]4}| dd¡}d}| | dd¡d|t
||ƒf¡ qÂ| |¡ dd dd„ |D ƒ¡ d }|  d¡}|dk �r:tdƒ‚|  d¡}|dk �rVtdƒ‚|  d¡}| d|… }|dk�r‚| |d… n
| |d… }d| }|| | S )z=Return a runtime with one lazily compiled closure per opcode.l   ±yn< i'íQr   i   iÿÿÿad  return function(ctx, ins)
local q,V,top,ups,va,nva,rb=ctx.q,ctx.V,ctx.top,ctx.ups,ctx.va,ctx.nva,ctx.rb
local K,pack,unpack,cell,cellval,cellput,mkclos,truthy,ENV,callwith,CELL_MT,boxed=ctx.K,ctx.pack,ctx.unpack,ctx.cell,ctx.cellval,ctx.cellput,ctx.mkclos,ctx.truthy,ctx.ENV,ctx.callwith,ctx.CELL_MT,ctx.boxed
local pc=ctx.pc
if ctx.q==nil then return end
z"
ctx.pc=pc
ctx.top=top
return
end
z
end
z	(?<!\.)\bz\bé   zdreturn function(ctx, ins)
if ctx.q == nil then
local x = 0
if x ~= 0 then return end
end
return
end
i    i   Fz{
z,
c                 s  s2   | ]*\}}}}d ||rdnd|t |ƒf V  qdS )z[%d]={t=%s,s=%d,x=%s}ÚtrueÚfalseN)r   )r/   ÚoprG   r   Úencr   r   r   ra   †   s   
ÿz(build_handler_runtime.<locals>.<genexpr>z
}zfunction V.exec(r   zV.exec not foundzlocal M = {}zM not foundz-- Binary graph reader.Nan  
local H = %s

local function h_unhex(s)
	local out = {}
	for i = 1, #s, 2 do
		out[#out + 1] = string.char(tonumber(s:sub(i, i + 1), 16))
	end
	return table.concat(out)
end

local function h_decrypt(hex, seed)
	local s = h_unhex(hex)
	local state = bit32.bxor(seed, 0x9E3779B9)
	local out = {}
	for i = 1, #s do
		state = bit32.bxor(state, bit32.lshift(state, 13))
		state = bit32.bxor(state, bit32.rshift(state, 17))
		state = bit32.bxor(state, bit32.lshift(state, 5))
		out[i] = string.char(bit32.bxor(s:byte(i), bit32.band(state, 255)))
	end
	return table.concat(out)
end

local function h_get(op)
	local rec = H[op]
	if not rec then error('', 0) end
	if not rec.fn then
		local src = h_decrypt(rec.x, rec.s)
		local f = loadstring or load
		local factory = f(src)
		if not factory then error('', 0) end
		rec.fn = factory()
	end
	return rec
end

function V.exec(pid, ups, ...)
	local p = V.protos[pid]
	if not p then error('', 0) end
	local q = {}
	local rb = V.regbase or 0
	local np = p.params
	local nargs = select('#', ...)
	for i = 1, np do
		q[rb + i - 1] = (select(i, ...))
	end
	local va, nva = {}, 0
	if p.vararg then
		nva = nargs - np
		for i = 1, nva do
			va[i] = select(np + i, ...)
		end
	end
	local code = p.code
	local n = #code
	local pc = 1
	local top = rb - 1
	local ctx = {
		q = q, V = V, ups = ups, va = va, nva = nva, rb = rb,
		top = top, pc = pc, K = K, pack = pack, unpack = unpack,
		cell = cell, cellval = cellval, cellput = cellput,
		mkclos = mkclos, truthy = truthy, ENV = ENV, callwith = callwith, CELL_MT = CELL_MT,
		boxed = p.boxed or {},
	}
	while pc >= 1 and pc <= n do
		local ins = code[pc]
		local op = V.opmap and V.opmap[ins[1]] or bit32.bxor(ins[1], V.opkey)
		local rec = h_get(op)
		ctx.pc, ctx.top = pc, top
		if rec.t then
			local r = pack(rec.fn(ctx, ins))
			return unpack(r, 1, r.n)
		end
		rec.fn(ctx, ins)
		pc, top = ctx.pc, ctx.top
	end
end
)rH   ÚrandomÚRandomr   Ú	randrangeri   Úitemsr8   ÚsubÚescaper*   r   r#   Úshuffler   Úfindr7   )r+   rj   r@   r`   ZrecordsrF   rE   rG   r   Zhnamesr(   rg   ÚnewZ	encryptedrn   r^   ZdecoyÚtableZexec_atZ	suffix_atZ	decode_atÚprefixÚsuffixZnew_execr   r   r   Úbuild_handler_runtime^   sd    
÷úùÿ
úúö
ÿ
þý




"N²Or|   )r   )Ú__doc__Ú
__future__r   rp   r8   r   r'   r*   rH   ri   r|   r   r   r   r   Ú<module>   s   