Skip to content

"Conditional jump or move depends on uninitialised value(s)" on feature(generator) #47253

Closed
@dwrensha

Description

@dwrensha

Valgrind reports use of uninitialized memory in the following program, which was reduced from tokio-rs/tokio-timer#36 and alexcrichton/futures-await#47.

// main.rs
#![feature(conservative_impl_trait, generators, generator_trait)]

pub type Poll<T, E> = Result<Async<T>, E>;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Async<T> {
    Ready(T),
    NotReady,
}

pub trait Future {
    type Item;
    type Error;
    fn poll(&mut self) -> Poll<Self::Item, Self::Error>;
}

impl<F, T, E> Future for Option<F> where F: Future<Item=T, Error=E> {
    type Item = Option<T>;
    type Error = E;
    fn poll(&mut self) -> Poll<Option<T>, E> {
        match *self {
            None => Ok(Async::Ready(None)),
            Some(ref mut x) => match x.poll() {
                Ok(Async::Ready(t)) => Ok(Async::Ready(Some(t))),
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Err(e) => Err(e),
            }
        }
    }
}

pub mod __rt {
    pub use std::ops::Generator;
    use super::Poll;
    use super::{Future, Async};
    use std::ops::GeneratorState;

    pub trait MyFuture<T: IsResult>: Future<Item=T::Ok, Error = T::Err> {}

    impl<F, T> MyFuture<T> for F
        where F: Future<Item = T::Ok, Error = T::Err > + ?Sized,
              T: IsResult
    {}

    pub trait IsResult {
        type Ok;
        type Err;

        fn into_result(self) -> Result<Self::Ok, Self::Err>;
    }
    impl<T, E> IsResult for Result<T, E> {
        type Ok = T;
        type Err = E;

        fn into_result(self) -> Result<Self::Ok, Self::Err> { self }
    }

    pub struct GenFuture<T>(pub T);

    pub enum Mu {}

    impl<T> Future for GenFuture<T>
        where T: Generator<Yield = Async<Mu>>,
              T::Return: IsResult,
    {
        type Item = <T::Return as IsResult>::Ok;
        type Error = <T::Return as IsResult>::Err;

        fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
            match self.0.resume() {
                GeneratorState::Yielded(Async::NotReady)
                    => Ok(Async::NotReady),
                GeneratorState::Yielded(Async::Ready(mu))
                    => match mu {},
                GeneratorState::Complete(e)
                    => e.into_result().map(Async::Ready),
            }
        }
    }
}

pub struct Foo {
    _a: Option<usize>,
    _b: Option<String>,
}

fn ola() -> impl __rt::MyFuture<Result<(), String>> + 'static {
    __rt::GenFuture(move || -> Result<(), String> {
        let _f = Foo { _a: None, _b: None };
        yield Async::NotReady;
        return Ok(());
    })
}

fn main() {
    let ft = ola();
    let _ = Some(ft).poll();
}
$ rustc -v -V
rustc 1.25.0-nightly (6828cf901 2018-01-06)
binary: rustc
commit-hash: 6828cf90146c7fefc4ba4f16dffe75f763f2d910
commit-date: 2018-01-06
host: x86_64-unknown-linux-gnu
release: 1.25.0-nightly
LLVM version: 4.0
$ rustc main.rs
$ valgrind ./main
==2217== Memcheck, a memory error detector
==2217== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2217== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2217== Command: ./main
==2217== 
==2217== Conditional jump or move depends on uninitialised value(s)
==2217==    at 0x10FAF4: <core::option::Option<F> as main::Future>::poll (in /home/dwrensha/Desktop/main)
==2217==    by 0x10F59A: main::main (in /home/dwrensha/Desktop/main)
==2217==    by 0x10F7E2: std::rt::lang_start::{{closure}} (in /home/dwrensha/Desktop/main)
==2217==    by 0x119E17: {{closure}} (rt.rs:59)
==2217==    by 0x119E17: _ZN3std9panicking3try7do_call17hffb5315d0c0f678dE.llvm.3A805FA6 (panicking.rs:480)
==2217==    by 0x123D9E: __rust_maybe_catch_panic (lib.rs:102)
==2217==    by 0x11034F: try<i32,closure> (panicking.rs:459)
==2217==    by 0x11034F: catch_unwind<closure,i32> (panic.rs:365)
==2217==    by 0x11034F: std::rt::lang_start_internal (rt.rs:58)
==2217==    by 0x10F7C6: std::rt::lang_start (in /home/dwrensha/Desktop/main)
==2217==    by 0x10F62D: main (in /home/dwrensha/Desktop/main)
==2217== 
==2217== Conditional jump or move depends on uninitialised value(s)
==2217==    at 0x10FB06: <core::option::Option<F> as main::Future>::poll (in /home/dwrensha/Desktop/main)
==2217==    by 0x10F59A: main::main (in /home/dwrensha/Desktop/main)
==2217==    by 0x10F7E2: std::rt::lang_start::{{closure}} (in /home/dwrensha/Desktop/main)
==2217==    by 0x119E17: {{closure}} (rt.rs:59)
==2217==    by 0x119E17: _ZN3std9panicking3try7do_call17hffb5315d0c0f678dE.llvm.3A805FA6 (panicking.rs:480)
==2217==    by 0x123D9E: __rust_maybe_catch_panic (lib.rs:102)
==2217==    by 0x11034F: try<i32,closure> (panicking.rs:459)
==2217==    by 0x11034F: catch_unwind<closure,i32> (panic.rs:365)
==2217==    by 0x11034F: std::rt::lang_start_internal (rt.rs:58)
==2217==    by 0x10F7C6: std::rt::lang_start (in /home/dwrensha/Desktop/main)
==2217==    by 0x10F62D: main (in /home/dwrensha/Desktop/main)
==2217== 
==2217== 
==2217== HEAP SUMMARY:
==2217==     in use at exit: 0 bytes in 0 blocks
==2217==   total heap usage: 6 allocs, 6 frees, 2,000 bytes allocated
==2217== 
==2217== All heap blocks were freed -- no leaks are possible
==2217== 
==2217== For counts of detected and suppressed errors, rerun with: -v
==2217== Use --track-origins=yes to see where uninitialised values come from
==2217== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions