2

I am running f:

contract Test {
    function f() {
        f();
    }
}

which produces VM Exception: invalid opcode in browser-solidity. Is that a bug or expected behavior?

2 Answers 2

2

Seems to be a bug in the ethereumjs-vm that browser-solidity uses via universal-dapp.js.

runCode.js has odd code...

  function iterateVm (done) {
    if (runState.stack.length > 1024) {
      return done(ERROR.INVALID_OPCODE)
    }

...because the stack length is different from the depth, which is checked against the 1024 (value of fees.stackLimit.v) in opFns.js:

  // increment the runState.depth
  callOptions.depth = runState.depth + 1

  if (runState.depth >= fees.stackLimit.v ...

If the stack length check is correct, it could at least return a different that would avoid confusing the depth limit error with an invalid opcode.


Note: the following code is an internal function call that's "translated into simple jumps inside the EVM". This means that the stack depth will not increase.

contract Test {
    function f() {
        f();
    }
}

An external function call is needed to increase the stack depth, use this.f(). Explicitly labelling the function as external (or public) also improves clarity.

contract Test {
    function f() external {
        this.f();
    }
}

Furthermore, the EIP150 hardfork has made breaching the stack depth practically impossible (since all gas would be exhausted first):

Supersede the "hard limit" max call stack depth with a softer limit, where creating a deep call tower would require an exponentially growing amount of gas. This completely removes call stack depth limit attacks as a category of issue that contract developers should have to worry about...

2
contract Test {
    function f() {
        f();
    }
}

it will provoke an infinite recursive call. So it is not a solidity browser bug.

try something like :

contract C {
function g(uint a) returns (uint ret) { return f(); }
function f() returns (uint ret) { return g(7) + f(); }
}

These function calls are translated into simple jumps inside the EVM.

Edit : the error is generated by a stack-length of 1024 so the compiler could no more jump to the destination (every f() call performs a Jump to Jumpdest).

74 JUMPDEST
75 PUSH 50
77 PUSH 4a
79 JUMP

every recursive call (..=>97=>74=>97...) 0X50 is added to the stack until we reach the stake limit length then the error jumps out. This error will be fired while the contract has enough remaining gas (so no outOfGas exception).

2
  • I know this is an infinite recursive call but therefore I was expecting an outOfGas or stackDepth exception. Why invalid opcode? A simple jump shouldnt be an invalid opcode.
    – SCBuergel
    Commented Nov 5, 2016 at 23:30
  • 1
    please read the edit note in my previous answer
    – Badr Bellaj
    Commented Nov 6, 2016 at 0:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.