Skip to content

Conversation

@saethlin
Copy link
Contributor

The fixes in #280 missed one instance of UB. The get_unchecked_mut
inside VacantEntry::Insert can be out of bounds of the initialized
region of the backing Vec. When that happens, the call is UB. This is
detected both by the standard library's debug assertions which can be
enabled with -Zbuild-std and with Miri but only with
-Zmiri-tag-raw-pointers.

This also adds inherent as_ptr and as_mut_ptr methods to Vec which
shadow those provided by the Deref to a slice. Without this shadowing,
the change from get_unchecked_mut to as_mut_ptr.add wouldn't actually
fix the problem identified by the debug assertions or Miri, it just
hides it from the debug assertions. The core problem is that references
narrow provenance, so if we want to access outside of the initialized
region of a Vec we need to get a pointer to the array without passing
through a reference to the initialized region first. The pointers from
these shadowing methods can be used to access anywhere in the allocation,
whereas vec.as_slice().as_ptr() would be UB to use for access into the
uninitialized region.

The fixes in rust-embedded#280 missed one instance of UB. The get_unchecked_mut
inside VacantEntry::Insert can be out of bounds of the initialized
region of the backing Vec. When that happens, the call is UB. This is
detected both by the standard library's debug assertions which can be
enabled with -Zbuild-std and with Miri but only with
-Zmiri-tag-raw-pointers.

This also adds inherent as_ptr and as_mut_ptr methods to Vec which
shadow those provided by the Deref to a slice. Without this shadowing,
the change from get_unchecked_mut to as_mut_ptr.add wouldn't actually
fix the problem identified by the debug assertions or Miri, it just
hides it from the debug assertions. The core problem is that references
narrow provenance, so if we want to access outside of the initialized
region of a Vec we need to get a pointer to the array without passing
through a reference to the initialized region first. The pointers from
these shadowing methods can be used to access anywhere in the allocation,
whereas vec.as_slice().as_ptr() would be UB to use for access into the
uninitialized region.
Copy link
Member

@japaric japaric 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 the PR

@japaric
Copy link
Member

japaric commented Jun 20, 2022

bors r+

@bors
Copy link
Contributor

bors bot commented Jun 20, 2022

Build succeeded:

@bors bors bot merged commit 344629e into rust-embedded:master Jun 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants