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

Using ? can lead to stack corruption in non-linear code. #200

Closed
tgolsson opened this issue Dec 6, 2020 · 0 comments · Fixed by #246
Closed

Using ? can lead to stack corruption in non-linear code. #200

tgolsson opened this issue Dec 6, 2020 · 0 comments · Fixed by #246
Labels
bug Something isn't working

Comments

@tgolsson
Copy link
Contributor

tgolsson commented Dec 6, 2020

This is an interesting case:

struct Foo {
	x,
	y,
}

struct Bar {
	x, 
	y,
}

impl Bar {
	fn from_foo(foo) {
		Some(Self {
			x: foo.x?,
			y: foo.y?,
		})
	}
}

pub fn main() {
	let f = Foo { x: Some(1), y: None };
	Bar::from_foo(f)
}

If the first element is Some, any following None will cause the VM to error out:

➜ cargo run --bin rune -- --dump-instructions -t miscomp.rn
    Finished dev [unoptimized + debuginfo] target(s) in 0.08s
     Running `target/debug/rune --dump-instructions -t miscomp.rn`
# instructions
fn main() (0xde7d86e18013c5c8):
  0000 = push 1
  0001 = call 0xf39f074fddf64c6b, 1 // variant ::std::option::Option::Some
  0002 = call 0x68988acb6b2de244, 0 // variant ::std::option::Option::None
  0003 = struct 0x30d77e445d4bc057, 0
  0004 = copy 0 // var `f`
  0005 = call 0x94fbe6278aba2ca5, 1 // fn Bar::from_foo
  0006 = clean 1
  0007 = return

fn Bar::from_foo(foo) (0x94fbe6278aba2ca5):
  0008 = copy 0 // var `foo`
  0009 = object-index-get 0
  0010 = dup
  0011 = is-value
  0012 = jump-if 2 // label:try_not_error_2
  0013 = clean 1
  0014 = return
try_not_error_2:
  0015 = unwrap
  0016 = copy 0 // var `foo`
  0017 = object-index-get 1
  0018 = dup
  0019 = is-value
  0020 = jump-if 2 // label:try_not_error_3
  0021 = clean 1
  0022 = return
try_not_error_3:
  0023 = unwrap
  0024 = struct 0x9a4ef349214d9ab1, 0
  0025 = call 0xf39f074fddf64c6b, 1 // variant ::std::option::Option::Some
  0026 = clean 1
  0027 = return
# strings
0xcd01b01a74097893 = "x"
0xef5992decfa6104f = "y"
# object keys
0 = ["x", "y"]
fn main() (0xde7d86e18013c5c8):
  0000 = push 1
  0001 = call 0xf39f074fddf64c6b, 1 // variant ::std::option::Option::Some
  0002 = call 0x68988acb6b2de244, 0 // variant ::std::option::Option::None
  0003 = struct 0x30d77e445d4bc057, 0
  0004 = copy 0 // var `f`
  0005 = call 0x94fbe6278aba2ca5, 1 // fn Bar::from_foo
fn Bar::from_foo(foo) (0x94fbe6278aba2ca5):
  0008 = copy 0 // var `foo`
  0009 = object-index-get 0
  0010 = dup
  0011 = is-value
  0012 = jump-if 2 // label:try_not_error_2
try_not_error_2:
  0015 = unwrap
  0016 = copy 0 // var `foo`
  0017 = object-index-get 1
  0018 = dup
  0019 = is-value
  0020 = jump-if 2 // label:try_not_error_3
  0021 = clean 1
  0022 = return
== ! (stack error: tried to access out-of-bounds stack entry (at inst 22)) (231.437µs)
error: virtual machine error
   ┌─ miscomp.rn:15:20
   │
15 │                 y: foo.y?
   │                    ^^^^^^ stack error: tried to access out-of-bounds stack entry

As far as I can tell this comes from the fact that the original foo is still on the stack when returning:

[2020-12-06T20:05:05Z TRACE runestick::vm] 21: clean 1
    1+0 = Foo { x: Some(1), y: None }
    1+1 = None
  miscomp.rn:15  -                 y: foo.y?
  0022 = return

and it should likely be cleaned here as well too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
2 participants