History

Merge pull request #1116 from martinvonz/push-rlxsnxnlnkmp

fix pointer aliasing an other issues in ItemSliceSend

Sebastian Thiel committed 2 years ago

Commit 613f0182 parents c65b80b 4f5ab363 files · +33 −16Browse files

Unified · Split

3 files
  1. gix-pack/src/cache/delta/traverse/mod.rs +1 −5
  2. gix-pack/src/cache/delta/traverse/resolve.rs +3 −3
  3. gix-pack/src/cache/delta/traverse/util.rs +29 −8
gix-pack/src/cache/delta/traverse/mod.rs+1−5
@@ -130,7 +130,6 @@ where · 129 unmodified lines
130130 };
131131 size_progress.init(None, progress::bytes());
132132 let size_counter = size_progress.counter();
133− let child_items = self.child_items.as_mut_slice();
134133 let object_progress = OwnShared::new(Mutable::new(object_progress));
135134
136135 let start = std::time::Instant::now();
@@ -138,10 +137,7 @@ where · 1 unmodified line
138137 &mut self.root_items,
139138 thread_limit,
140139 {
141− let child_items = ItemSliceSend(std::ptr::slice_from_raw_parts_mut(
142− child_items.as_mut_ptr(),
143− child_items.len(),
144− ));
140+ let child_items = ItemSliceSend::new(&mut self.child_items);
145141 {
146142 let object_progress = object_progress.clone();
147143 move |thread_index| {
gix-pack/src/cache/delta/traverse/resolve.rs+3−3
@@ -17,13 +17,13 @@ use crate::{ · 16 unmodified lines
1717 data::EntryRange,
1818 };
1919
20−pub(crate) struct State<F, MBFN, T: Send> {
20+pub(crate) struct State<'items, F, MBFN, T: Send> {
2121 pub delta_bytes: Vec<u8>,
2222 pub fully_resolved_delta_bytes: Vec<u8>,
2323 pub progress: Box<dyn Progress>,
2424 pub resolve: F,
2525 pub modify_base: MBFN,
26− pub child_items: ItemSliceSend<Item<T>>,
26+ pub child_items: ItemSliceSend<'items, Item<T>>,
2727 }
2828
2929 #[allow(clippy::too_many_arguments)]
@@ -38,7 +38,7 @@ pub(crate) fn deltas<T, F, MBFN, E, R>( · 8 unmodified lines
3838 resolve,
3939 modify_base,
4040 child_items,
41− }: &mut State<F, MBFN, T>,
41+ }: &mut State<'_, F, MBFN, T>,
4242 resolve_data: &R,
4343 hash_len: usize,
4444 threads_left: &AtomicIsize,
gix-pack/src/cache/delta/traverse/util.rs+29−8
@@ -1,28 +1,49 @@
1+use std::marker::PhantomData;
2+
13 use crate::cache::delta::Item;
24
3−pub struct ItemSliceSend<T>(pub *mut [T])
5+pub(crate) struct ItemSliceSend<'a, T>
6+where
7+ T: Send,
8+{
9+ items: *mut T,
10+ phantom: PhantomData<&'a T>,
11+}
12+
13+impl<'a, T> ItemSliceSend<'a, T>
414 where
5− T: Send;
15+ T: Send,
16+{
17+ pub fn new(items: &'a mut [T]) -> Self {
18+ ItemSliceSend {
19+ items: items.as_mut_ptr(),
20+ phantom: PhantomData,
21+ }
22+ }
23+}
624
725 /// SAFETY: This would be unsafe if this would ever be abused, but it's used internally and only in a way that assure that the pointers
826 /// don't violate aliasing rules.
9−impl<T> Clone for ItemSliceSend<T>
27+impl<T> Clone for ItemSliceSend<'_, T>
1028 where
1129 T: Send,
1230 {
1331 fn clone(&self) -> Self {
14− ItemSliceSend(self.0)
32+ ItemSliceSend {
33+ items: self.items,
34+ phantom: self.phantom,
35+ }
1536 }
1637 }
1738
1839 // SAFETY: T is `Send`, and we only ever access one T at a time. And, ptrs need that assurance, I wonder if it's always right.
1940 #[allow(unsafe_code)]
20−unsafe impl<T> Send for ItemSliceSend<T> where T: Send {}
41+unsafe impl<T> Send for ItemSliceSend<'_, T> where T: Send {}
2142
2243 /// An item returned by `iter_root_chunks`, allowing access to the `data` stored alongside nodes in a [`Tree`].
23−pub struct Node<'a, T: Send> {
44+pub(crate) struct Node<'a, T: Send> {
2445 pub item: &'a mut Item<T>,
25− pub child_items: ItemSliceSend<Item<T>>,
46+ pub child_items: ItemSliceSend<'a, Item<T>>,
2647 }
2748
2849 impl<'a, T: Send> Node<'a, T> {
@@ -57,7 +78,7 @@ impl<'a, T: Send> Node<'a, T> { · 28 unmodified lines
5778 // SAFETY: The resulting mutable pointer cannot be yielded by any other node.
5879 #[allow(unsafe_code)]
5980 Node {
60− item: &mut unsafe { &mut *children.0 }[index as usize],
81+ item: unsafe { &mut *children.items.add(index as usize) },
6182 child_items: children.clone(),
6283 }
6384 })