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

Soundness issue in Zip::next() specialization #81740

Closed
Qwaz opened this issue Feb 4, 2021 · 5 comments · Fixed by #81741
Closed

Soundness issue in Zip::next() specialization #81740

Qwaz opened this issue Feb 4, 2021 · 5 comments · Fixed by #81741
Labels
A-iterators Area: Iterators C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness P-high High priority T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@Qwaz
Copy link
Contributor

Qwaz commented Feb 4, 2021

#[inline]
fn next(&mut self) -> Option<(A::Item, B::Item)> {
if self.index < self.len {
let i = self.index;
self.index += 1;
// SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
unsafe {
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
}
} else if A::may_have_side_effect() && self.index < self.a.size() {
// match the base implementation's potential side effects
// SAFETY: we just checked that `self.index` < `self.a.len()`
unsafe {
self.a.__iterator_get_unchecked(self.index);
}
self.index += 1;
None
} else {
None
}
}

/// 2. If `self: !Clone`, then `get_unchecked` is never called with the same
/// index on `self` more than once.

There is a panic safety issue in Zip::next() that allows to call __iterator_get_unchecked() to the same index twice. __iterator_get_unchecked() is called at line 204 and the index is updated at line 206. If line 204 panics, the index is not updated and the subsequent next() call will use the same index for __iterator_get_unchecked(). This violates the second safety requirement of TrustedRandomAccess.

Here is a playground link that demonstrates creating two mutable references to the same memory location without using unsafe Rust.

@Qwaz Qwaz added the C-bug Category: This is a bug. label Feb 4, 2021
@Qwaz
Copy link
Contributor Author

Qwaz commented Feb 4, 2021

The bug fixed by this PR seems to have the same consequence, but it didn't get the unsound label.
#80670

@sdroege
Copy link
Contributor

sdroege commented Feb 4, 2021

Seems like this would be fixed by simply doing the same as in the first branch of the if and incrementing the self.index beforehand. Are you creating a PR for this?

@Qwaz
Copy link
Contributor Author

Qwaz commented Feb 4, 2021

Seems like this would be fixed by simply doing the same as in the first branch of the if and incrementing the self.index beforehand.

Agreed :)

Are you creating a PR for this?

Not in the meantime. Fill free to work on a PR if you are interested.

@sdroege
Copy link
Contributor

sdroege commented Feb 4, 2021

Not in the meantime. Fill free to work on a PR if you are interested.

Sure, why not :)

@jonas-schievink jonas-schievink added the I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness label Feb 4, 2021
@rustbot rustbot added the I-prioritize Issue: Indicates that prioritization has been requested for this issue. label Feb 4, 2021
@camelid camelid added T-libs Relevant to the library team, which will review and decide on the PR/issue. A-iterators Area: Iterators labels Feb 5, 2021
@apiraino apiraino added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Feb 5, 2021
@apiraino
Copy link
Contributor

apiraino commented Feb 5, 2021

Assigning P-high as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 11, 2021
…pecialization-panic-safety, r=KodrAus

Increment `self.index` before calling `Iterator::self.a.__iterator_ge…

…`t_unchecked` in `Zip` `TrustedRandomAccess` specialization

Otherwise if `Iterator::self.a.__iterator_get_unchecked` panics the
index would not have been incremented yet and another call to
`Iterator::next` would read from the same index again, which is not
allowed according to the API contract of `TrustedRandomAccess` for
`!Clone`.

Fixes rust-lang#81740
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 12, 2021
…pecialization-panic-safety, r=KodrAus

Increment `self.index` before calling `Iterator::self.a.__iterator_ge…

…`t_unchecked` in `Zip` `TrustedRandomAccess` specialization

Otherwise if `Iterator::self.a.__iterator_get_unchecked` panics the
index would not have been incremented yet and another call to
`Iterator::next` would read from the same index again, which is not
allowed according to the API contract of `TrustedRandomAccess` for
`!Clone`.

Fixes rust-lang#81740
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Feb 12, 2021
…pecialization-panic-safety, r=KodrAus

Increment `self.index` before calling `Iterator::self.a.__iterator_ge…

…`t_unchecked` in `Zip` `TrustedRandomAccess` specialization

Otherwise if `Iterator::self.a.__iterator_get_unchecked` panics the
index would not have been incremented yet and another call to
`Iterator::next` would read from the same index again, which is not
allowed according to the API contract of `TrustedRandomAccess` for
`!Clone`.

Fixes rust-lang#81740
@bors bors closed this as completed in 86a4b27 Feb 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-iterators Area: Iterators C-bug Category: This is a bug. I-unsound Issue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/Soundness P-high High priority T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants