UnderminersTeam / UndertaleModTool

The most complete tool for modding, decompiling and unpacking Undertale (and other GameMaker games!)
GNU General Public License v3.0
1.18k stars 225 forks source link

Booleans converted to int for binary operations are treated as double #1686

Closed Rob23oba closed 5 months ago

Rob23oba commented 8 months ago

Describe the bug

When you use a boolean expression inside of a binary operation like addition, subtraction, multiplication or modulo, the compiler will convert it into an int, but mistreats it as double for the binary operation, which can cause games to crash upon execution with an error "Malformed variable".

Example:

a = 1 + (a > 0)

gets compiled into:

pushi.e 1
push.v self.a
pushi.e 0
cmp.i.v GT
conv.b.i
add.d.i
pop.v.d self.a

The boolean to int conversion (conv.b.i) is followed by a variable-double addition (add.d.v). However, it should actually be a variable-int addition (add.i.v) since the boolean was converted to int, not double.

This issue lies in the implementation of Compiler::AssemblyWriter::ConvertTypeToBinaryOp:

private static void ConvertTypeForBinaryOp(CodeWriter cw, Lexer.Token.TokenKind kind)
{
    var type = cw.typeStack.Peek();
    switch (kind)
    {
        // ...
        case Lexer.Token.TokenKind.Plus:
        case Lexer.Token.TokenKind.Minus:
        case Lexer.Token.TokenKind.Times:
        case Lexer.Token.TokenKind.Div:
        case Lexer.Token.TokenKind.Mod:
            if (type == DataType.BOOLEAN)
            {
                cw.typeStack.pop();
                cw.Emit(Opcode.Conv, type, DataType.Int32);
                cw.typeStack.Push(DataType.Double); // Wrongly pushes double as a data type after converting to int
            }
            break;
        // ...
    }
}

Reproducing steps

  1. Go into any code inside of any GameMaker game
  2. Add the following statements at the end:
    a = 1 + (a > 0)
  3. Go to the end of the disassembly tab
  4. The assembly will wrongly contain conv.b.i followed by add.d.i

Setup Details

  1. Affects the latest version (v:0.5.1.0)
  2. Should work on all operating systems and projects
Miepee commented 5 months ago

fixed by #1766