Fix potential undefined behavior (#13555)

* Switch to ouroboros 0.5.1

* Update other lock files
This commit is contained in:
joshua-maros 2020-11-13 01:12:41 -08:00 committed by GitHub
parent cbcde43765
commit a8a77614fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 48 additions and 40 deletions

8
Cargo.lock generated
View File

@ -2410,9 +2410,9 @@ dependencies = [
[[package]] [[package]]
name = "ouroboros" name = "ouroboros"
version = "0.4.0" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "776469997c56d7130b691a5edea1cbe63d7fef495f98b1b0ced0f3a5571c37aa" checksum = "cc04551635026d3ac7bc646698ea1836a85ed2a26b7094fe1d15d8b14854c4a2"
dependencies = [ dependencies = [
"ouroboros_macro", "ouroboros_macro",
"stable_deref_trait", "stable_deref_trait",
@ -2420,9 +2420,9 @@ dependencies = [
[[package]] [[package]]
name = "ouroboros_macro" name = "ouroboros_macro"
version = "0.4.0" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85165ba45bb44e86ddb86e33ad92640522d572229c5c326eb7eb81ef31b06ce7" checksum = "cec33dfceabec83cd0e95a5ce9d20e76ab3a5cbfef59659b8c927f69b93ed8ae"
dependencies = [ dependencies = [
"Inflector", "Inflector",
"proc-macro2 1.0.24", "proc-macro2 1.0.24",

View File

@ -1259,9 +1259,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "ouroboros" name = "ouroboros"
version = "0.4.0" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "776469997c56d7130b691a5edea1cbe63d7fef495f98b1b0ced0f3a5571c37aa" checksum = "cc04551635026d3ac7bc646698ea1836a85ed2a26b7094fe1d15d8b14854c4a2"
dependencies = [ dependencies = [
"ouroboros_macro", "ouroboros_macro",
"stable_deref_trait", "stable_deref_trait",
@ -1269,9 +1269,9 @@ dependencies = [
[[package]] [[package]]
name = "ouroboros_macro" name = "ouroboros_macro"
version = "0.4.0" version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85165ba45bb44e86ddb86e33ad92640522d572229c5c326eb7eb81ef31b06ce7" checksum = "cec33dfceabec83cd0e95a5ce9d20e76ab3a5cbfef59659b8c927f69b93ed8ae"
dependencies = [ dependencies = [
"Inflector", "Inflector",
"proc-macro2 1.0.24", "proc-macro2 1.0.24",

View File

@ -29,7 +29,7 @@ memmap = "0.7.0"
num-derive = { version = "0.3" } num-derive = { version = "0.3" }
num-traits = { version = "0.2" } num-traits = { version = "0.2" }
num_cpus = "1.13.0" num_cpus = "1.13.0"
ouroboros = "0.4.0" ouroboros = "0.5.1"
rand = "0.7.0" rand = "0.7.0"
rayon = "1.4.1" rayon = "1.4.1"
regex = "1.3.9" regex = "1.3.9"

View File

@ -32,9 +32,9 @@ pub struct AccountMapEntryInner<T> {
#[self_referencing] #[self_referencing]
pub struct ReadAccountMapEntry<T: 'static> { pub struct ReadAccountMapEntry<T: 'static> {
pub owned_entry: AccountMapEntry<T>, owned_entry: AccountMapEntry<T>,
#[borrows(owned_entry)] #[borrows(owned_entry)]
pub slot_list_guard: RwLockReadGuard<'this, SlotList<T>>, slot_list_guard: RwLockReadGuard<'this, SlotList<T>>,
} }
impl<T: Clone> ReadAccountMapEntry<T> { impl<T: Clone> ReadAccountMapEntry<T> {
@ -47,19 +47,19 @@ impl<T: Clone> ReadAccountMapEntry<T> {
} }
pub fn slot_list(&self) -> &SlotList<T> { pub fn slot_list(&self) -> &SlotList<T> {
&*self.slot_list_guard &*self.borrow_slot_list_guard()
} }
pub fn ref_count(&self) -> &AtomicU64 { pub fn ref_count(&self) -> &AtomicU64 {
&self.owned_entry.ref_count &self.borrow_owned_entry_contents().ref_count
} }
} }
#[self_referencing] #[self_referencing]
pub struct WriteAccountMapEntry<T: 'static> { pub struct WriteAccountMapEntry<T: 'static> {
pub owned_entry: AccountMapEntry<T>, owned_entry: AccountMapEntry<T>,
#[borrows(owned_entry)] #[borrows(owned_entry)]
pub slot_list_guard: RwLockWriteGuard<'this, SlotList<T>>, slot_list_guard: RwLockWriteGuard<'this, SlotList<T>>,
} }
impl<T: 'static + Clone> WriteAccountMapEntry<T> { impl<T: 'static + Clone> WriteAccountMapEntry<T> {
@ -72,15 +72,18 @@ impl<T: 'static + Clone> WriteAccountMapEntry<T> {
} }
pub fn slot_list(&mut self) -> &SlotList<T> { pub fn slot_list(&mut self) -> &SlotList<T> {
&*self.slot_list_guard &*self.borrow_slot_list_guard()
} }
pub fn slot_list_mut(&mut self) -> &mut SlotList<T> { pub fn slot_list_mut<RT>(
&mut *self.slot_list_guard &mut self,
user: impl for<'this> FnOnce(&mut RwLockWriteGuard<'this, SlotList<T>>) -> RT,
) -> RT {
self.with_slot_list_guard_mut(user)
} }
pub fn ref_count(&self) -> &AtomicU64 { pub fn ref_count(&self) -> &AtomicU64 {
&self.owned_entry.ref_count &self.borrow_owned_entry_contents().ref_count
} }
// Try to update an item in the slot list the given `slot` If an item for the slot // Try to update an item in the slot list the given `slot` If an item for the slot
@ -97,12 +100,12 @@ impl<T: 'static + Clone> WriteAccountMapEntry<T> {
assert!(same_slot_previous_updates.len() <= 1); assert!(same_slot_previous_updates.len() <= 1);
if let Some((list_index, (s, previous_update_value))) = same_slot_previous_updates.pop() { if let Some((list_index, (s, previous_update_value))) = same_slot_previous_updates.pop() {
reclaims.push((*s, previous_update_value.clone())); reclaims.push((*s, previous_update_value.clone()));
self.slot_list_mut().remove(list_index); self.slot_list_mut(|list| list.remove(list_index));
} else { } else {
// Only increment ref count if the account was not prevously updated in this slot // Only increment ref count if the account was not prevously updated in this slot
self.ref_count().fetch_add(1, Ordering::Relaxed); self.ref_count().fetch_add(1, Ordering::Relaxed);
} }
self.slot_list_mut().push((slot, account_info)); self.slot_list_mut(|list| list.push((slot, account_info)));
} }
} }
@ -301,22 +304,24 @@ impl<T: 'static + Clone> AccountsIndex<T> {
// if this account has no more entries. // if this account has no more entries.
pub fn purge(&self, pubkey: &Pubkey) -> (SlotList<T>, bool) { pub fn purge(&self, pubkey: &Pubkey) -> (SlotList<T>, bool) {
let mut write_account_map_entry = self.get_account_write_entry(pubkey).unwrap(); let mut write_account_map_entry = self.get_account_write_entry(pubkey).unwrap();
let slot_list = write_account_map_entry.slot_list_mut(); write_account_map_entry.slot_list_mut(|slot_list| {
let reclaims = self.get_rooted_entries(&slot_list); let reclaims = self.get_rooted_entries(slot_list);
slot_list.retain(|(slot, _)| !self.is_root(*slot)); slot_list.retain(|(slot, _)| !self.is_root(*slot));
(reclaims, slot_list.is_empty()) (reclaims, slot_list.is_empty())
})
} }
pub fn purge_exact(&self, pubkey: &Pubkey, slots: HashSet<Slot>) -> (SlotList<T>, bool) { pub fn purge_exact(&self, pubkey: &Pubkey, slots: HashSet<Slot>) -> (SlotList<T>, bool) {
let mut write_account_map_entry = self.get_account_write_entry(pubkey).unwrap(); let mut write_account_map_entry = self.get_account_write_entry(pubkey).unwrap();
let slot_list = write_account_map_entry.slot_list_mut(); write_account_map_entry.slot_list_mut(|slot_list| {
let reclaims = slot_list let reclaims = slot_list
.iter() .iter()
.filter(|(slot, _)| slots.contains(&slot)) .filter(|(slot, _)| slots.contains(&slot))
.cloned() .cloned()
.collect(); .collect();
slot_list.retain(|(slot, _)| !slots.contains(slot)); slot_list.retain(|(slot, _)| !slots.contains(slot));
(reclaims, slot_list.is_empty()) (reclaims, slot_list.is_empty())
})
} }
// Given a SlotSlice `L`, a list of ancestors and a maximum slot, find the latest element // Given a SlotSlice `L`, a list of ancestors and a maximum slot, find the latest element
@ -442,7 +447,9 @@ impl<T: 'static + Clone> AccountsIndex<T> {
max_clean_root: Option<Slot>, max_clean_root: Option<Slot>,
) { ) {
if let Some(mut locked_entry) = self.get_account_write_entry(pubkey) { if let Some(mut locked_entry) = self.get_account_write_entry(pubkey) {
self.purge_older_root_entries(locked_entry.slot_list_mut(), reclaims, max_clean_root); locked_entry.slot_list_mut(|slot_list| {
self.purge_older_root_entries(slot_list, reclaims, max_clean_root);
});
} }
} }
@ -453,12 +460,13 @@ impl<T: 'static + Clone> AccountsIndex<T> {
reclaims: &mut SlotList<T>, reclaims: &mut SlotList<T>,
) { ) {
if let Some(mut locked_entry) = self.get_account_write_entry(pubkey) { if let Some(mut locked_entry) = self.get_account_write_entry(pubkey) {
let slot_list = locked_entry.slot_list_mut(); locked_entry.slot_list_mut(|slot_list| {
slot_list.retain(|(slot, entry)| { slot_list.retain(|(slot, entry)| {
if *slot == purge_slot { if *slot == purge_slot {
reclaims.push((*slot, entry.clone())); reclaims.push((*slot, entry.clone()));
} }
*slot != purge_slot *slot != purge_slot
});
}); });
} }
} }