GithubHelp home page GithubHelp logo

Comments (9)

erikzhang avatar erikzhang commented on June 12, 2024 2

The behavior of JMP* is not changed. I think the comments should be modified.

from neo-vm.

dauTT avatar dauTT commented on June 12, 2024 2

Yes behavior of JMP* is the same. 👍

from neo-vm.

erikzhang avatar erikzhang commented on June 12, 2024 1

JMP 0000 is an infinite loop.

from neo-vm.

igormcoelho avatar igormcoelho commented on June 12, 2024

When I wrote that, it made sense to me 🤔 sorry about that 😝
In fact code has changed recently, so it's even clearer now perhaps (although logic should be the same... let's check).
This is an infinite loop code:

public static void Main()
        {
            while(true);
        }

The generated NVM is: 00c56b620000, which means:

00 PUSH0  #An empty array of bytes is pushed onto the stack
c5 NEWARRAY  #
6b TOALTSTACK  # Puts the input onto the top of the alt stack. Removes it from the main stack.
62 JMP 0000 # 0

So, here's the instruction counter i.
^00c56b620000
i=0: PUSH0
00^c56b620000
i=1: NEWARRAY
00c5^6b620000
i=2: TOALTSTACK
00c56b^620000
i=3: JMP
Now, at this point, for JMP, it must read 2 bytes more (n=0x0000):
00c56b620000^
Offset value n is zero (and i=5). So, if it jumped i+n=5+0=5, it would be at the same place, and read the next instruction (after the while).
So, instead, it must jump to i+n-3=5+0-3=2 (the same state before reading the JMP). What happened now is that instruction has already been processed in this "new" format, so jump can go directly to i+n (but i is probably still 2 at this point). It is just important to know that the jump reference is related to the start position of JMP instruction, not the end.

There are some test cases here, you can take a look just to make sure everything is fine (if we don't have one specific like this, we can make one to be sure it is fine ;) )

Source: https://neocompiler.io

from neo-vm.

dauTT avatar dauTT commented on June 12, 2024

@igormcoelho ,
Thanks for detail explanation which mirror the description of the opcode JMP. However I am not sure that the current code does what you said. Try to debug the following code:

 public void Test()
        {

            ExecutionEngine e = new ExecutionEngine(null, new Crypto());

            e.LoadScript("00c56b620000".FromHexString());

            e.Execute();


        }

image

As you can see the instruction pointer is set again to 3 forever because fvalue=true and n=0.

In my opinion either we should change the code to reflect the description of the opcodes or viceversa:
The current code mirror this description in my opinion:

/// Reads a 2-byte value n and a jump is performed to relative position n.
        /// </summary>
        JMP = 0x62,
        /// <summary>
        /// A boolean value b is taken from main stack and reads a 2-byte value n, if b is True then a jump is performed to relative position n. If b is False advance the instruction pointer of 3
        /// </summary>
        JMPIF = 0x63,
        /// <summary>
        /// A boolean value b is taken from main stack and reads a 2-byte value n, if b is False then a jump is performed to relative position n. If b is True advance the instruction pointer of 3.
        /// </summary>
        JMPIFNOT = 0x64,

So the current logic is not the same as the old logic.

from neo-vm.

igormcoelho avatar igormcoelho commented on June 12, 2024

Sorry @dauTT , I don't have a C# debugger.. hahaha so I only have my eyes for these things :P
Anyway, if value is 3 on instruction counter, 3 represents the beggining of JMP opcode. So, a next jump to position 3 would keep it in the same position, right?
I agree, we need to update the description, specially now that we don't have an explicit subtraction (we had that before).

from neo-vm.

dauTT avatar dauTT commented on June 12, 2024

The old logic seems to me more corret than the current one: 😄
https://github.com/neo-project/neo-vm/blob/v2.4.0/src/neo-vm/ExecutionEngine.cs

case OpCode.JMP:
                    case OpCode.JMPIF:
                    case OpCode.JMPIFNOT:
                        {
                            int offset = context.OpReader.ReadInt16();
                            offset = context.InstructionPointer + offset - 3;
                            if (offset < 0 || offset > context.Script.Length)
                            {
                                State |= VMState.FAULT;
                                return;
                            }
                            bool fValue = true;
                            if (opcode > OpCode.JMP)
                            {
                                CheckStackSize(false, -1);
                                fValue = context.EvaluationStack.Pop().GetBoolean();

                                if (opcode == OpCode.JMPIFNOT)
                                    fValue = !fValue;
                            }
                            if (fValue)
                                context.InstructionPointer = offset;
                            break;
                        }

and I think we would need to roll back to the old logic to maintain backward compatibility.

from neo-vm.

igormcoelho avatar igormcoelho commented on June 12, 2024

No man... no rolling back, that's why we have tests now 😆
Are you sure there's no test here to verify a similar case?
Let's try a simple if-else structure and see if the correct value is returned on stack.

from neo-vm.

igormcoelho avatar igormcoelho commented on June 12, 2024

Good. So, how can we explain it better on comment? :)

from neo-vm.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.