Skip to content

Commit 1383b0d

Browse files
committed
fix pointer aliasing in in_parallel.rs
In `in_parallel_with_slice()`, there's a `&mut *input.0` that creates a `&mut [I]` of the whole slice in `Input`. The same value is created in multiple threads, thus potentially resulting in multiple threads having mutable references to the same value. This patch fixes that by instead only getting mutable pointers to individual values. It does so by storing a `*mut T` in `Input` instead of the current `*mut [I]`, and then using `pointer::add()` to get pointers to individual elements. Thanks to @Ralith for bringing this up and proposing the solution in our review of unsafe code at Google.
1 parent d75159c commit 1383b0d

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

gix-features/src/parallel/in_parallel.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,12 @@ where
229229
.expect("valid name");
230230

231231
let input_len = input.len();
232-
struct Input<I>(*mut [I])
232+
struct Input<I>(*mut I)
233233
where
234234
I: Send;
235235

236-
// SAFETY: I is Send + Sync, so is a *mut [I]
236+
// SAFETY: I is Send, and we only use the pointer for creating new
237+
// pointers (within the input slice) from the threads.
237238
#[allow(unsafe_code)]
238239
unsafe impl<I> Send for Input<I> where I: Send {}
239240

@@ -245,7 +246,7 @@ where
245246
let new_thread_state = new_thread_state.clone();
246247
let state_to_rval = state_to_rval.clone();
247248
let mut consume = consume.clone();
248-
let input = Input(input as *mut [I]);
249+
let input = Input(input.as_mut_ptr());
249250
move || {
250251
let _ = &input;
251252
threads_left.fetch_sub(1, Ordering::SeqCst);
@@ -264,7 +265,7 @@ where
264265
let item = {
265266
#[allow(unsafe_code)]
266267
unsafe {
267-
&mut (&mut *input.0)[input_index]
268+
&mut *input.0.add(input_index)
268269
}
269270
};
270271
if let Err(err) = consume(item, &mut state, threads_left, stop_everything) {

0 commit comments

Comments
 (0)