[NoW] Luac crashes when trying to display undefined instruction

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

[NoW] Luac crashes when trying to display undefined instruction

Egor Skriptunoff-2
"NoW" means "Nitpicking on Wednesdays"
(unimportant questions about Lua design and implementation)

 
 
The problem:
"luac" fails to display a bytecode containing VM instruction with reserved opcode.
 
Suggestion:
It would be better to display undefined instruction as four numbers (opcode,A,B,C) instead of get crashed.
 
Why it may be useful:
Some Lua scripting environments add new instructions to Lua VM.
For example, "GameGuardian" (a memory patching tool for cracking android games) implements Lua 5.2 with extended syntax.
Opcode 43 is reserved шn PUC Lua 5.2 VM, but in GameGuardian Lua VM this opcode is used for VM instruction "bitwise OR".
Yes, they have both the function "bit32.bor(x,y)" and the operator "x|y" simultaneously in the language.
I guess GameGuardian is not the only occasion when Lua implementation has new VM instructions added without modifying the original instructions.
It would be nice if such bytecode would be viewable with standard "luac" utility.
 
P.S.
The "format" byte in the header of a GameGuardian bytecode is zero.

Reply | Threaded
Open this post in threaded view
|

Re: [NoW] Luac crashes when trying to display undefined instruction

Luiz Henrique de Figueiredo
> "luac" fails to display a bytecode containing VM instruction with reserved opcode.

Could you please send me a sample file? Thanks.

> The "format" byte in the header of a GameGuardian bytecode is zero.

They should have changed that! It's there precisely to alert the loader!

Reply | Threaded
Open this post in threaded view
|

Re: [NoW] Luac crashes when trying to display undefined instruction

Egor Skriptunoff-2
On Wed, Jan 23, 2019 at 11:57 PM Luiz Henrique de Figueiredo wrote:
> "luac" fails to display a bytecode containing VM instruction with reserved opcode.

Could you please send me a sample file? Thanks.


 
The crash could be reproduced on any Luac version.
For example, to create such bytecode for little-endian Luac 5.3, it is enough to replace the "return" instruction with reserved opcode=63
 
bad_bytecode = string.dump(load""):gsub(string.char(38,0,128,0), string.char(63, 0, 0, 0))
 

 

> The "format" byte in the header of a GameGuardian bytecode is zero.

They should have changed that! It's there precisely to alert the loader!



If GG script isn't using extended syntax (new bitwise operators)
then the resulting GG bytecode is compatible with PUC Lua 5.2 bytecode.
And any PUC Lua 5.2 bytecode is a correct GG bytecode too.
(Assuming endianness and bitness are the same, of course.)
Probably, in this case, using format=0 is OK?

Reply | Threaded
Open this post in threaded view
|

Re: [NoW] Luac crashes when trying to display undefined instruction

Luiz Henrique de Figueiredo
> The crash could be reproduced on any Luac version.
> For example, to create such bytecode for little-endian Luac 5.3, it is enough to replace the "return" instruction with reserved opcode=63

Ok, the problem is the following line in PrintCode, which only works
if o < NUM_OPCODES :

printf("%-9s\t",luaP_opnames[o]);

Otherwise, we index beyond the size of luaP_opnames and all bets are
off. (I don't get a crash in macOS, but rather "__mode" is printed.)
GameGuardian should have updated the list of instructions and
NUM_OPCODES, and all would be well.

>> > The "format" byte in the header of a GameGuardian bytecode is zero.
>>
>> They should have changed that! It's there precisely to alert the loader!
>
> If GG script isn't using extended syntax (new bitwise operators)
> then the resulting GG bytecode is compatible with PUC Lua 5.2 bytecode.
> And any PUC Lua 5.2 bytecode is a correct GG bytecode too.
> (Assuming endianness and bitness are the same, of course.)
> Probably, in this case, using format=0 is OK?

That's one interpretation. But it also means that plain Lua will try
to load GG bytecode and then fail horribly at execution.

Reply | Threaded
Open this post in threaded view
|

Re: [NoW] Luac crashes when trying to display undefined instruction

Egor Skriptunoff-2
On Fri, Jan 25, 2019 at 1:42 AM Luiz Henrique de Figueiredo wrote:
> The crash could be reproduced on any Luac version.
> For example, to create such bytecode for little-endian Luac 5.3, it is enough to replace the "return" instruction with reserved opcode=63

Ok, the problem is the following line in PrintCode, which only works
if o < NUM_OPCODES :

printf("%-9s\t",luaP_opnames[o]);




Yes, that's array index out of bounds error.
Could you please fix it in Luac?
(for example, to display opcode when opname doesn't exist)
Reply | Threaded
Open this post in threaded view
|

Re: [NoW] Luac crashes when trying to display undefined instruction

Luiz Henrique de Figueiredo
> Yes, that's array index out of bounds error.
> Could you please fix it in Luac?
> (for example, to display opcode when opname doesn't exist)

We could fix this opname issue as suggested, but there are probably
other issues like that, eg indexing the constant array or the locvars
array. Keep in mind that luac, like the rest of Lua, assumes that the
bytecode is correct. We have long given up checking bytecode for
correctness. I don't think we want to litter luac with checks that
might give the wrong impression.

Reply | Threaded
Open this post in threaded view
|

Re: [NoW] Luac crashes when trying to display undefined instruction

Rena
On Fri, Jan 25, 2019, 05:50 Luiz Henrique de Figueiredo <[hidden email] wrote:
> Yes, that's array index out of bounds error.
> Could you please fix it in Luac?
> (for example, to display opcode when opname doesn't exist)

We could fix this opname issue as suggested, but there are probably
other issues like that, eg indexing the constant array or the locvars
array. Keep in mind that luac, like the rest of Lua, assumes that the
bytecode is correct. We have long given up checking bytecode for
correctness. I don't think we want to litter luac with checks that
might give the wrong impression.

Perhaps the best solution here is a fork of luac that does try to deal with such cases.