Skip to content

return break returns pointer/uninitialised data. #6675

Closed
@huonw

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.

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