Skip to content

Segfault due to using return pointer directly #34592

Closed
@alexcrichton

Description

@alexcrichton

First reported at rust-lang-deprecated/rustc-serialize#154, it looks like the code in that issue will segfault on all platforms and isn't related to the allocator in question, it's just a bad free. It looks like the expansion of #[derive(RustcDecodable)] is the function that's segfaulting, specifically:

extern crate rustc_serialize;

use rustc_serialize::*;

pub struct Request {
    pub id: String,
    pub arg: String,
}

impl Decodable for Request {
    fn decode<D: Decoder>(d: &mut D) -> Result<Request, D::Error> {
        d.read_struct("Request", 2, |d| {
            Ok(Request {
                id: match d.read_struct_field("id", 0, Decodable::decode) {
                    Ok(v) => v,
                    Err(e) => return Err(e),
                },
                arg: match d.read_struct_field("arg", 1, Decodable::decode) {
                    Ok(v) => v,
                    Err(e) => return Err(e),
                },
            })
        })
    }
}

In this function the closure should detect that it has nested returns and therefore the closure should write intermediate results into a local alloca of what to return. Instead, though, no alloca is created an results are stored directly into the return pointer.

The fault looks like it happens when:

  • The decode function is called, read_struct is called, then the closure is called.
  • The first call to read_struct_field succeeds, so the string is stored in the id field directly into the return pointer
  • The second call to read_struct_field fails, returning an error
  • The compiler writes the result (Err(D::Error)) into the return pointer
  • The compiler then attempts to free the string stored to id

Basically at that point it's freeing arbitrary data because the string has already been paved over. I have been unable to reproduce this with a smaller example because everything I do seems to trigger usage of an alloca for the return value (which should be happening here). Maybe someone else knows though how to trigger this with a smaller example.

In any case though this segafult happens on nightly/beta/stable, but would be very good to fix!

cc @rust-lang/compiler

also nominating

Metadata

Metadata

Assignees

Labels

A-codegenArea: Code generationT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions