Skip to content

SpecExtend for TrustedLen is unsound #89948

Open
@lcnr

Description

@lcnr
#![feature(trusted_len)]
use std::iter::TrustedLen;
use std::marker::PhantomData;

pub struct MaybeTrusted<'a, I>(I, PhantomData<fn(&'a ()) -> &'a ()>);

impl<'a, I: Iterator> Iterator for MaybeTrusted<'a, I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.0.size_hint()
    }
}

/// This is safe, as a `'static` version of this struct can only be created
/// using a trusted iterator.
unsafe impl<I: Iterator> TrustedLen for MaybeTrusted<'static, I> {}
impl<I: TrustedLen> MaybeTrusted<'static, I> {
    pub fn new(value: I) -> Self {
        MaybeTrusted(value, PhantomData)
    }
}

/// `I` might not implement `TrustedLen`, but that's ok,
/// because you can't get a `MaybeTrusted<'static, I>` from this.
pub fn not_trusted<I: Iterator, T>(i: I, f: impl for<'a> FnOnce(MaybeTrusted<'a, I>) -> T) -> T {
    f(MaybeTrusted(i, PhantomData))
}

// In a separate crate:

struct Liar(usize);
impl Iterator for Liar {
    type Item = usize;
    fn next(&mut self) -> Option<Self::Item> {
        if self.0 < 10000 {
            self.0 += 1;
            Some(self.0)
        } else {
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        // happy little accident, but ok, doesn't implemented `TrustedLen`.
        let len = self.0.saturating_sub(10000);
        (len, Some(len))
    }
}

fn main() {
    not_trusted(Liar(0), |iter| iter.collect::<Vec<_>>());
}

results in:

Segmentation fault (core dumped)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-iteratorsArea: IteratorsC-bugCategory: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-libsRelevant to the library team, which will review and decide on the PR/issue.requires-nightlyThis issue requires a nightly compiler in some way.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions