![]() # Objective `QueryIter::sort_by()` is unsound. It passes the lens items with the full `'w` lifetime, and a malicious user could smuggle them out of the closure where they could alias with the query results. ## Solution Make the sort closures generic in the lifetime parameter of the lens item. This ensures the lens items cannot outlive the call to the closure. ## Testing Added a compile-fail test that demonstrates the unsound pattern. ## Migration Guide The `sort` family of methods on `QueryIter` unsoundly gave access `L::Item<'w>` with the full `'w` lifetime. It has been shortened to `L::Item<'w>` so that items cannot escape the comparer. If you get lifetime errors using these methods, you will need to make the comparer generic in the new lifetime. Often this can be done by replacing named `'w` with `'_`, or by replacing the use of a function item with a closure. ```rust // Before: Now fails with "error: implementation of `FnMut` is not general enough" query.iter().sort_by::<&C>(Ord::cmp); // After: Wrap in a closure query.iter().sort_by::<&C>(|l, r| Ord::cmp(l, r)); query.iter().sort_by::<&C>(comparer); // Before: Uses specific `'w` lifetime from some outer scope // now fails with "error: implementation of `FnMut` is not general enough" fn comparer(left: &&'w C, right: &&'w C) -> Ordering { /* ... */ } // After: Accepts any lifetime using inferred lifetime parameter fn comparer(left: &&C, right: &&C) -> Ordering { /* ... */ } |
||
---|---|---|
.. | ||
entity_ref_mut_lifetime_safety.rs | ||
entity_ref_mut_lifetime_safety.stderr | ||
query_exact_sized_iterator_safety.rs | ||
query_exact_sized_iterator_safety.stderr | ||
query_iter_combinations_mut_iterator_safety.rs | ||
query_iter_combinations_mut_iterator_safety.stderr | ||
query_iter_many_mut_iterator_safety.rs | ||
query_iter_many_mut_iterator_safety.stderr | ||
query_lens_lifetime_safety.rs | ||
query_lens_lifetime_safety.stderr | ||
query_lifetime_safety.rs | ||
query_lifetime_safety.stderr | ||
query_to_readonly.rs | ||
query_to_readonly.stderr | ||
query_transmute_safety.rs | ||
query_transmute_safety.stderr | ||
system_param_derive_readonly.rs | ||
system_param_derive_readonly.stderr | ||
system_query_get_lifetime_safety.rs | ||
system_query_get_lifetime_safety.stderr | ||
system_query_get_many_lifetime_safety.rs | ||
system_query_get_many_lifetime_safety.stderr | ||
system_query_get_many_mut_lifetime_safety.rs | ||
system_query_get_many_mut_lifetime_safety.stderr | ||
system_query_iter_lifetime_safety.rs | ||
system_query_iter_lifetime_safety.stderr | ||
system_query_iter_many_mut_lifetime_safety.rs | ||
system_query_iter_many_mut_lifetime_safety.stderr | ||
system_query_iter_sort_lifetime_safety.rs | ||
system_query_iter_sort_lifetime_safety.stderr | ||
system_query_set_get_lifetime_safety.rs | ||
system_query_set_get_lifetime_safety.stderr | ||
system_query_set_iter_lifetime_safety.rs | ||
system_query_set_iter_lifetime_safety.stderr | ||
system_state_get_lifetime_safety.rs | ||
system_state_get_lifetime_safety.stderr | ||
system_state_iter_lifetime_safety.rs | ||
system_state_iter_lifetime_safety.stderr | ||
system_state_iter_mut_overlap_safety.rs | ||
system_state_iter_mut_overlap_safety.stderr | ||
world_query_derive.rs | ||
world_query_derive.stderr |