viruscamp / luadec

Lua Decompiler for lua 5.1 , 5.2 and 5.3
1.14k stars 343 forks source link

SETLIST with c==0 #41

Closed viruscamp closed 8 years ago

viruscamp commented 8 years ago

SETLIST A B C R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B

If C is 0, the next instruction is cast as an integer, and used as the C value.This happens only when operand C is unable to encode the block number,i.e. when C > 511, equivalent to an array index greater than 25550.
如果 C 是 0,下一条指令被转换为整数并用作 C 的值。只有当操作数 C 不能编码块编号时出现该情况,例如当 C > 511 时,等同于数组索引大于25550。

        case OP_SETLIST:
        {
            if (c==0) {
                c = code[pc+1];
                pc++;
            }
            TRY(SetList(F, a, b, c));
            break;
        }
viruscamp commented 8 years ago
case OP_SETLIST:
{
    if (c==0) {
        Instruction i_next_arg = code[++pc];
#if LUA_VERSION_NUM == 501
        c = i_next_arg;
#endif
#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
        if (GET_OPCODE(i_next_arg) == OP_EXTRAARG) {
            c = GETARG_Ax(i_next_arg);
        } else {
            SET_ERROR(F, "SETLIST with c==0, but not followed by EXTRAARG.");
        }
#endif
    }
    TRY(SetList(F, a, b, c));
    break;
}
viruscamp commented 8 years ago

add test cases: issue41_gen_large_table.lua

-- setlist c=0 when top>=25550
-- loadkx and extraarg when top>=2^18

print("local x={")

local top = arg[1] or 2^18
local count = 0
for i = 0, top do
    io.stdout:write(i,",")
    count = count + 1
    if count == 20 then
        io.stdout:write("\n")
        count = 0
    end
end
if count ~= 0 then
    io.stdout:write("\n")
end
print("}")
lua issue41_gen_large_table.lua 25550 > issue41_setlist0.lua
lua issue41_gen_large_table.lua 262142 > issue41_51_most_const.lua
lua issue41_gen_large_table.lua 262144 > issue41_loadkx.lua

lua issue41_gen_large_table.lua 262143 lua51 cannot process but lua52 53 gen without loadkx