Description
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 theid
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