Skip to content

array_to_bounded_vec is dangerous #9854

@nventuro

Description

@nventuro

This is utils::arrays::array_to_bounded_vec, which is used throughout the kernel data builders:

pub fn array_to_bounded_vec<T, let N: u32>(array: [T; N]) -> BoundedVec<T, N>
where
    T: Empty + Eq,
{
    let mut len = 0;
    for elem in array {
        if !is_empty(elem) {
            len += 1;
        }
    }

    BoundedVec { storage: array, len }
}

Note how array is not mutated at all: the implementation assumes that all empty values are located at the end of the array, and attempts to only count the non-empty ones. This is extremely dangerous for two reasons:

a) if array were to have even a single empty value with a lower index than any non-empty value, the non-empty value would be lost, and BoundedVec's storage would be corrupt
b) if T::empty() returns true for any value that is not std::mem::zeroed(), BoundedVec's storage will again be corrupt. This is because BoundedVec assumes that unused storage elements are cleared, and blindly compares all of storage in its eq implementation. An empty value that is not zeroed would cause for the resulting BoundedVec to not be equal to one that is created by inserting all of its elements into a new one, since the 'empty' storage would not be the same.

Additionally, array_to_bounded_vec does not convey this handling of empty values, and seems to imply the function would behave the same as BoundedVec::from_array, which it does not.

I stumbled upon this when clearing warnings: this function emits some as BoundedVec's storage and len properties are private as they are not meant to be directly accessed (due to issues like the ones described here).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-securityArea: Relates to security. Something is insecure.C-protocol-circuitsComponent: Protocol circuits (kernel & rollup)team-turingLeila's team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions