Skip to content

Commit 142e7f3

Browse files
Backport soundness fix (#3685)
#3001 discovered a soundness bug in World::resource_scope, this PR backports the fix with a smaller PR to patch out the bug sooner. Fixes #3147
1 parent e928acb commit 142e7f3

File tree

1 file changed

+12
-6
lines changed
  • crates/bevy_ecs/src/world

1 file changed

+12
-6
lines changed

crates/bevy_ecs/src/world/mod.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -926,24 +926,30 @@ impl World {
926926
// the ptr value / drop is called when T is dropped
927927
unsafe { column.swap_remove_and_forget_unchecked(0) }
928928
};
929-
// SAFE: pointer is of type T
930-
let value = Mut {
931-
value: unsafe { &mut *ptr.cast::<T>() },
929+
// SAFE: pointer is of type T and valid to move out of
930+
// Read the value onto the stack to avoid potential mut aliasing.
931+
let mut value = unsafe { std::ptr::read(ptr.cast::<T>()) };
932+
let value_mut = Mut {
933+
value: &mut value,
932934
ticks: Ticks {
933935
component_ticks: &mut ticks,
934936
last_change_tick: self.last_change_tick(),
935937
change_tick: self.change_tick(),
936938
},
937939
};
938-
let result = f(self, value);
940+
let result = f(self, value_mut);
941+
assert!(!self.contains_resource::<T>());
939942
let resource_archetype = self.archetypes.resource_mut();
940943
let unique_components = resource_archetype.unique_components_mut();
941944
let column = unique_components
942945
.get_mut(component_id)
943946
.unwrap_or_else(|| panic!("resource does not exist: {}", std::any::type_name::<T>()));
947+
948+
// Wrap the value in MaybeUninit to prepare for passing the value back into the ECS
949+
let mut nodrop_wrapped_value = std::mem::MaybeUninit::new(value);
944950
unsafe {
945-
// SAFE: pointer is of type T
946-
column.push(ptr, ticks);
951+
// SAFE: pointer is of type T, and valid to move out of
952+
column.push(nodrop_wrapped_value.as_mut_ptr() as *mut _, ticks);
947953
}
948954
result
949955
}

0 commit comments

Comments
 (0)