Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stack corruption #761

Closed
mhermier opened this issue Jun 10, 2020 · 9 comments
Closed

Stack corruption #761

mhermier opened this issue Jun 10, 2020 · 9 comments

Comments

@mhermier
Copy link
Contributor

Here is a reduced test to the long standing stack corruption issue:

// Level of required nesting is dependant on INITIAL_CALL_FRAMES
var Fn1 = Fn.new {|acc| Fiber.yield(acc) }
var Fn2 = Fn.new {|acc| Fn1.call(acc, null) }
var Fn3 = Fn.new {|acc| Fn2.call(acc, null) }
var Fn4 = Fn.new {|acc| Fn3.call(acc, null) }
var Fiber1 = Fiber.new { Fn4.call(42) }

System.print(Fiber1.call()) // expect: 42
System.print(Fiber1.call("caramba")) // expect: caramba

Instead of returning caramba, second call to it returns 42. I have not been able to weaponize it to make the test crash, but at least it can be tested somehow.

@mhermier
Copy link
Contributor Author

Another one based on #770

var Fib1 = Fn.new {|n|
  if (n <= 2) {
    return 1
  } else {
    return Fib1.call(n-1) + Fib1.call(n-2)
  }
}

var Fib2 = Fn.new {|n|
  if (n <= 2) {
    return 1
  } else {
    var left = Fib2.call(n-1)
    var right = Fib2.call(n-2)
    return left + right
  }
}

System.print(Fib2.call(12)) // expect: 144
System.print(Fib1.call(12)) // expect: 144

Just in case, reducing it to:

var Fib = Fn.new {|n|
  if (n <= 2) {
    return 1
  } else {
    return Fib.call(n-1) + Fib.call(n-2)
  }
}

System.print(Fib.call(12)) // expect: 144

Trigger the bug but does not make it visible to user for some reasons.

@ruby0x1
Copy link
Member

ruby0x1 commented Aug 3, 2020

Thanks, I think we have a fix for this, at least in my engine where I have a fix applied for another bug, this one is giving expected results too.

@mhermier
Copy link
Contributor Author

mhermier commented Aug 4, 2020

Could you issue a pull request of that fix before merging? Since that stuff is in the critical path, and can have possible huge impacts in speed.

I also have a crude patch that fix that issue by doing a STORE_FRAME/LOAD_FRAME around the switch (method->type) block that work quite well. It is a little bit expensive (in term of time), but seems to cover all the case.

Another solution would be to revert, the function call change.

So before you push, please allow to evaluate your solution.

@ruby0x1
Copy link
Member

ruby0x1 commented Aug 4, 2020

Don't forget the benchmarks exist.

The first is baseline, the second 2 are the "heavy" fix. STORE/LOAD frame around the whole primitive block.

ConEmu64_oY1TIcZLBO

This is the better fix, just waiting for Bob to give me some feedback before I bring it in.

ConEmu64_NQgRojGmQf

@mhermier
Copy link
Contributor Author

mhermier commented Aug 4, 2020 via email

@mhermier
Copy link
Contributor Author

#801 Seems to be another variation of the issue.

@mathewmariani
Copy link
Contributor

When will this MR be available?

@ruby0x1
Copy link
Member

ruby0x1 commented Sep 1, 2020

I have no estimate. Waiting for @munificent to send some thoughts my way.

(It IS 2020 though, it's reasonable to expect some delay due to priorities)

@ruby0x1
Copy link
Member

ruby0x1 commented Sep 18, 2020

All cases listed above are working as expected with #807 merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants