metaworm/luac-parser-rs

Sometimes the decompiler reference nonexistent label

Opened this issue · 1 comments

Consider this simple Lua 5.2 function:

-- test_function.lua
function is_function_type(v)
	return v ~= nil and type(v) == "function"
end

Compile with LuaC

luac test_function.lua

The decompilation result will be like this:

-- filename: @..\..\test_compile.lua
-- version: lua52
-- line: [0, 0] id: 0
is_function_type = function(r0_1)
  -- line: [1, 3] id: 1
  local r1_1 = nil	-- notice: implicit variable refs by block#[4]
  if r0_1 ~= nil then
    r1_1 = type(r0_1) == "function"
  else
    goto label_7	-- block#2 is visited secondly
  end
  return r1_1
end

Note that it tries to goto label_7 but label_7 is never defined anywhere.

to understand this problem, we must understand the nature of the decompilation process.
your code is compiled to the following by the lua 5.2 compiler:

if r0_1 ~= nil then goto label_2 end
goto label_7
::label_2::
r1_1 = _ENV["type"]
r2_1 = r0_1
r1_1 = r1_1(r2_1)
if r1_1 ~= "function" then goto label_7 end
goto label_8
::label_7::
r1_1 = false ; goto label_9
::label_8::
r1_1 = true 
::label_9::
return r1_1

the issue occurs, because label_7 has multiple predecessors.
if you load this file up in metaworm's luadec and check out the graph view, you'll be able to see exactly what i mean:
image

what happens is that the comparison is optimized into block#1, and the instruction at label_7 "disappears".

what seems like a simple issue at first becomes very difficult to tackle, because you must design an algorithm that correctly identifies these cases and solves them, no matter the amount of nested expressions, etc.