Skip to content

return break returns pointer/uninitialised data. #6675

Description

@huonw
pub fn p() -> uint { for 1.times { return break; } 0 }
pub fn p2() -> ~[u8] { for 1.times { return break; } ~[] }

pub fn ok() -> uint { for 1.times { return 123456789; } 0 }

fn main() {
    let y = p2(); // +
    println(fmt!("%?", p()));
    // *
    println(fmt!("%?", y));
}

Without optimisations:

140330640183752
/bin/bash: line 1: 30823 Segmentation fault      ./return-break

Or, if the let marked with + is moved to the *.

140236804280776
~[]
*** Error in `./return-break': free(): invalid pointer: 0x0000000000a02020 ***
[... snip ...]

With -O(the position of the let doesn't matter):

0
/bin/bash: line 1: 30884 Segmentation fault      ./return-break

Delving in to the unoptimised asm, the only difference between p and ok is:

; p
.LBB2_4:
    #APP
    # return break ; (return-break.rs:1:35: 1:48)
    #NO_APP
    movq    -24(%rbp), %rax
    movb    $1, (%rax)
    movb    $0, -1(%rbp) ; once, for `return`
    movb    $0, -1(%rbp) ; twice, for `break`
    jmp .LBB2_1

; ok
.LBB16_4:
    #APP
    # return 123456789; (return-break.rs:4:36: 4:52)
    #NO_APP
    movq    -24(%rbp), %rax
    movb    $1, (%rax)
    movb    $0, -1(%rbp)
    movq    -32(%rbp), %rcx
    movq    $123456789, (%rcx)
    jmp .LBB16_1

So it looks like the calling code assumes that (%rcx)/(-32(%rbp)) is filled as the return value, but it's not. Presumably return break should be a compile error (or be equivalent to break), as should more complicated code like

return match foo {
  Bar => break,
  Baz => 2
}

since it also has the same problem.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions