Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix integer overflow in BlobVec::push for ZST #10799

Merged
merged 1 commit into from
Jan 4, 2024

Conversation

stepancheg
Copy link
Contributor

reserve_exact is no-op for ZST because self.item_layout.size() > 0 is always false.

pub fn reserve_exact(&mut self, additional: usize) {
let available_space = self.capacity - self.len;
if available_space < additional && self.item_layout.size() > 0 {
// SAFETY: `available_space < additional`, so `additional - available_space > 0`
let increment = unsafe { NonZeroUsize::new_unchecked(additional - available_space) };
// SAFETY: not called for ZSTs
unsafe { self.grow_exact(increment) };
}
}

Then in push we just increase .len ignoring integer overflow.

pub unsafe fn push(&mut self, value: OwningPtr<'_>) {
self.reserve_exact(1);
let index = self.len;
self.len += 1;
self.initialize_unchecked(index, value);
}

@alice-i-cecile alice-i-cecile added C-Bug An unexpected or incorrect behavior A-ECS Entities, components, systems, and events labels Nov 29, 2023
@james7132 james7132 self-requested a review November 30, 2023 23:54
Copy link
Member

@james7132 james7132 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how this resolves the bug mentioned in the PR description.

The Rust standard library also has an unchecked addition in Vec::push. The corresponding grow method for RawVec also makes explicit checks to see if it's handling a ZST, which this PR is changing to be an unconditional assertion instead of a soft check.

The problem in the PR description is valid. We should not allow BlobVec's len to overflow, but I don't think the changes here are appropriate for addressing it.

crates/bevy_ecs/src/storage/blob_vec.rs Show resolved Hide resolved
@stepancheg
Copy link
Contributor Author

I'm not sure how this resolves the bug mentioned in the PR description.

Attempt to call resolve_exact(usize::MAX) with vec of len 20 will panic now.

The Rust standard library also has an unchecked addition in Vec::push

Because reserve calls above in std::vec::Vec guarantees that after call to reserve Vec has enough spare capacity. BlobVec::reserve_exact does not guarantee that. Which this PR fixes.

The corresponding grow method for RawVec also makes explicit checks to see if it's handling a ZST, which this PR is changing to be an unconditional assertion instead of a soft check.

This "soft check" is converted to panic in handle_reserve in the same file. Which is exactly the same this commit is doing: panicking on ZST in grow.

The removal of the check in reserve_exact means we do not guard against this panic.

I'm sorry, I don't understand.

This may cause panics on BlobVecs holding ZSTs

Correct. We should panic when attempting to add more than usize::MAX elements to BlobVec. It is the same behavior as Vec.

something that is not part of reserve_exact's defined interface, and something we must support.

The interface of reserve_exact is: if reserve_exact is successful (i.e. does not panic), push will be successful.

We should not allow BlobVec's len to overflow, but I don't think the changes here are appropriate for addressing it.

Is it possible you misunderstood this PR?

Otherwise, what do you suggest?

@stepancheg
Copy link
Contributor Author

Added a test.

Copy link
Member

@james7132 james7132 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for clarifying how you were approaching this. I think I see what you were going for here. This also removes yet another low level unsafe function from bevy_ecs, so it generally seems like a win to me. Only nit is that this is reliant on the current BlobVec initialization for ZSTs and that implicit reliance is not documented.

crates/bevy_ecs/src/storage/blob_vec.rs Show resolved Hide resolved
crates/bevy_ecs/src/storage/blob_vec.rs Show resolved Hide resolved
crates/bevy_ecs/src/storage/blob_vec.rs Show resolved Hide resolved
@stepancheg stepancheg force-pushed the blob-vec-zst branch 2 times, most recently from d3e6769 to b2a642b Compare December 1, 2023 07:36
@stepancheg
Copy link
Contributor Author

Added more comments.

crates/bevy_ecs/src/storage/blob_vec.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/storage/blob_vec.rs Outdated Show resolved Hide resolved
crates/bevy_ecs/src/storage/blob_vec.rs Outdated Show resolved Hide resolved
@stepancheg
Copy link
Contributor Author

Rephrased comments.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Jan 4, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Jan 4, 2024
Merged via the queue into bevyengine:main with commit cf70f53 Jan 4, 2024
23 checks passed
@stepancheg stepancheg deleted the blob-vec-zst branch January 4, 2024 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants