Skip to content

Soundness issue when the two uses of the `$count` expression evaluate to different things.

The implementation contains $count in two places

let mut vec = $crate::__ArrayVec::<_, {$count}>(unsafe {  });
while vec.0.len < $count {
    
}

These could evaluate to different things. Even though it's forced to be a const expression, so there won't be any run-time side-effects, a procedural macro could evaluate to two different literals when called twice in an expression like array![0; proc_macro_call!()]. (Recall that the outer macro call evaluates first.)

Furthermore, this is even exploitable without proc-macros by abusing the differences in type-inference information available at the two places (one is known to be T == usize, the other just needs usize: PartialOrd<T>) which can influence coercions in different ways:

use array_macro::array;

fn main() {
    impl PartialEq<Foo> for usize {
        fn eq(&self, _: &Foo) -> bool {
            *self == 0
        }
    }
    impl PartialOrd<Foo> for usize {
        fn partial_cmp(&self, _: &Foo) -> Option<std::cmp::Ordering> {
            self.partial_cmp(&0)
        }
    }


    trait Tr<P> {
        const CON: P;
    }
    const fn bar<P, T>(_: &T) -> P
    where
        (T,): Tr<P>,
    {
        <(T,)>::CON
    }

    impl Tr<usize> for ((),) {
        const CON: usize = 1;
    }

    struct Foo;

    impl Tr<Foo> for (&(),) {
        const CON: Foo = Foo;
    }

    let x = array![Box::new(String::new()); bar(&&() as _)];

    println!("{x:?}");
}
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.04s
     Running `target/debug/…CRATE_NAME…`
[1]    494953 segmentation fault (core dumped)  cargo run

One possible proposed fix: Add a function

pub fn __array_vec_capacity<T, const N: usize>(_: &__ArrayVec<T, N>) -> usize {
    N
}

and use while vec.0.len < $crate::__array_vec_capacity(&vec) for the loop.

Edited by Frank Steffahn
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information