Skip to content

Compiler accepts return mut ref to local var on no longer valid stackframe #46557

Closed
@CasualX

Description

@CasualX

Spotted on reddit: https://www.reddit.com/r/rust/comments/7i64sy/safe_function_returns_static_mut/
credit to jDomantas

I tried this code: playground

fn gimme_static_mut() -> &'static mut u32 {
    let ref mut x = 1234543;
    x
}

fn main() {
    let x = gimme_static_mut();
    let y = gimme_static_mut();
    *y = 42;
    let a = *x;
    println!("a: {}", a);
}

This is accepted by the compiler and prints 42.

I expected to see this happen: The program should be rejected by the compiler with a lifetime error

Instead this happened: The program was accepted and miscompiled badly

The assembly code clearly demonstrates the problem, a local variable is created for the literal, its address is taken and returned:

playground::gimme_static_mut:
.Lfunc_begin2:
	push	rbp
.Lcfi6:
.Lcfi7:
	mov	rbp, rsp
.Lcfi8:
	sub	rsp, 16
	lea	rax, [rbp - 4]
.Ltmp6:
	mov	dword ptr [rbp - 4], 1234543
	mov	qword ptr [rbp - 16], rax
	mov	rax, qword ptr [rbp - 16]
.Ltmp7:
	add	rsp, 16
	pop	rbp
	ret
.Ltmp8:
.Lfunc_end2:

Meta

Latest version on playground

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-NLLArea: Non-lexical lifetimes (NLL)A-borrow-checkerArea: The borrow checkerC-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessP-mediumMedium priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-stablePerformance or correctness regression from one stable version to another.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions