atrexus / unluau

A decompiler for Luau (Roblox's Lua based programming language: https://luau-lang.org/).
Apache License 2.0
87 stars 21 forks source link

An unknown error occured while decompiling the script: Value cannot be null. (Parameter 'source') #17

Closed strawbberrys closed 1 year ago

strawbberrys commented 1 year ago

Receiving this error when attempting to decompile the compiled version of the file below. This does seem like a pretty common error, but I don't see any issues created for it yet. (GitHub doesn't support uploading files beyond their whitelist which is why the file extensions are .txt)

sample.luau.txt sample-compiled.luau.txt

$ ./Unluau.CLI sample-compiled.luau --verbose
09:43:22 [Debug] Deserializer: Reading 18 strings from the string table
09:43:22 [Debug] Deserializer: Reading 3 functions from main bytecode pool
09:43:22 [Debug] Deserializer: Reading basic function prototype information
09:43:22 [Debug] Deserializer: Reading 28 instructions from function prototype body
09:43:22 [Debug] Deserializer: Reading 8 constants from function prototype body
09:43:22 [Debug] Deserializer: Reading basic function prototype information
09:43:22 [Debug] Deserializer: Reading 23 instructions from function prototype body
09:43:22 [Debug] Deserializer: Reading 11 constants from function prototype body
09:43:22 [Debug] Deserializer: Reading basic function prototype information
09:43:22 [Debug] Deserializer: Reading 46 instructions from function prototype body
09:43:22 [Debug] Deserializer: Reading 14 constants from function prototype body
    An unknown error occured while decompiling the script: Value cannot be null. (Parameter 'source')
Please create an issue at the GitHub repository here: https://github.com/valencefun/unluau/issues
atrexus commented 1 year ago

@strawbberrys After quite a long while of debugging and fixes I was able to get the decompiler to output the following (d03d7f6):

local upval0 = {}
upval0.__index = upval0
function upval0.new(arg1)
   local var0 = {}
   var0.name = arg1.name
   var0.items = {}
   print(`Store created with name {var0.name}`)
   local var1 = 0
   return setmetatable(var0, upval0)
end

function upval0.addItem(arg1, arg2)
   local var0 = table.clone(arg2)
   local var1 = nil
   table.insert(arg1.items, var0)
   print(`Item created with name {var0.name}`)
end

local var31 = {}
var31.name = "Shoes"
local var0 = upval0.new(var31)
local var34 = {}
var34.name = "Nike"
var34.stock = 99999
var34.cost = 50
var0:addItem(var34)
local var39 = {}
var39.name = "Gucci"
var39.stock = 10
var39.cost = 500
var0:addItem(var39)
return upval0

There are obviously many things wrong with this output, specifically: there are random assignments within each closure and the decompiler does not recognize addItem as a self inducing function. I am sure that the reason there are random assignments has to do with luau's relatively new FASTCALL operations, so I'll look into those. The self function issue may be quite difficult to solve as there is no explicit way of knowing if the first argument of a lua function refers to a metatable or literally anything else.

I will have to do a little more thinking to solve this issue, so if you have any ideas in mind please let me know!