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

Memory safety problem in insert_many() #53

Closed
Qwaz opened this issue Jan 8, 2021 · 9 comments
Closed

Memory safety problem in insert_many() #53

Qwaz opened this issue Jan 8, 2021 · 9 comments
Assignees
Milestone

Comments

@Qwaz
Copy link

Qwaz commented Jan 8, 2021

Hello, we recently reported a buffer overflow bug in SmallVec::insert_many() servo/rust-smallvec#252.

This crate contains a slightly older copy of insert_many() that has the same vulnerability.

/// Insert multiple elements at position `index`.
///
/// Shifts all elements before index to the back of the iterator.
/// It uses size hints to try to minimize the number of moves,
/// however, it does not rely on them. We cannot internally allocate, so
/// if we overstep the lower_size_bound, we have to do extensive
/// moves to shift each item back incrementally.
///
/// This implementation is adapted from [`smallvec`], which has a battle-tested
/// implementation that has been revised for at least a security advisory
/// warning. Smallvec is similarly licensed under an MIT/Apache dual license.
///
/// [`smallvec`]: https://github.com/servo/rust-smallvec

Please update the code when the fix is published.

Thanks!

@KamilaBorowska
Copy link

For what it's worth, the way this crate uses insert_many won't trigger the issue, but it's still worth fixing I would say.

myrrlyn added a commit that referenced this issue Apr 18, 2021
@myrrlyn
Copy link
Collaborator

myrrlyn commented Apr 18, 2021

Hi! Thank you for this report.

I am fairly confident that my commit addresses the concerns of an iterator that underestimates its contents. That said, I would appreciate a double check. Please close this issue if you believe my commit is correct, or comment if it requires further work.

@myrrlyn myrrlyn self-assigned this Apr 18, 2021
@Qwaz
Copy link
Author

Qwaz commented Apr 18, 2021

The patch breaks the element ordering:
[old head][new elements][old tail][new elements (extend)]

Maybe apply the patch from the upstream smallvec?
https://github.com/servo/rust-smallvec/pull/254/files#diff-b1a35a68f14e696205874893c07fd24fdb88882b47c23cc0e0c80a30c7d53759

@myrrlyn
Copy link
Collaborator

myrrlyn commented Apr 18, 2021

Gah. Figured I'd miss something. Thanks for the patch note. This ought to do it.

You know, there's a perfectly good .splice method that already does this work. You'd think they'd just copy alloc::Vec's homework on this one

myrrlyn added a commit that referenced this issue Apr 18, 2021
@Qwaz
Copy link
Author

Qwaz commented Apr 18, 2021

  1. Line 75-81 could be deleted for less distraction
  2. I didn't test it, but wouldn't it panic at runtime? The length is set to index and never changed before calling vec.insert(index + num_added, elem);, so I expect it would panic because index + num_added > index (=vec.len()).

Alexhuszagh added a commit that referenced this issue Apr 19, 2021
Default to 32-bit limbs if CARGO_CFG_TARGET_ARCH is not set. This way,
we do not rely on the host architecture for the fallback. 32-bit limbs
should generally be performant on most architectures.
Alexhuszagh pushed a commit that referenced this issue Apr 19, 2021
Alexhuszagh pushed a commit that referenced this issue Apr 19, 2021
Alexhuszagh added a commit that referenced this issue Apr 19, 2021
@Alexhuszagh
Copy link
Owner

@Qwaz I believe I've now addressed this, I've also independently tested the logic just to ensure it works with faulty iterators. I'll keep this issue open until the new version with the patch is released. The implementation is essentially identical to servo/rust-smallvec's current implementation, just to avoid any risks with unusual edge-cases.

Does this fix look satisfactory?

@Qwaz
Copy link
Author

Qwaz commented Apr 20, 2021

Thanks for the fix, it looks good.

@Alexhuszagh
Copy link
Owner

Alexhuszagh commented Apr 20, 2021

Wonderful, I'll keep this issue open until the newest version is released (and also backport it to maintained branches). So far this has been backported to every branch. Once again, thank you.

@Alexhuszagh Alexhuszagh added this to the 0.7.6 milestone Apr 20, 2021
Alexhuszagh added a commit that referenced this issue Apr 21, 2021
Alexhuszagh added a commit that referenced this issue Apr 21, 2021
Alexhuszagh added a commit that referenced this issue Apr 21, 2021
@Alexhuszagh
Copy link
Owner

Closed as of v0.4.8, v0.6.8, and v0.7.6. This did not affect the v0.5 branch, since that depends on stack-vector, which has patched it upstream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants