Skip to content

Commit 4f4a819

Browse files
authored
Rollup merge of #97316 - CAD97:bound-misbehavior, r=dtolnay
Put a bound on collection misbehavior As currently written, when a logic error occurs in a collection's trait parameters, this allows *completely arbitrary* misbehavior, so long as it does not cause undefined behavior in std. However, because the extent of misbehavior is not specified, it is allowed for *any* code in std to start misbehaving in arbitrary ways which are not formally UB; consider the theoretical example of a global which gets set on an observed logic error. Because the misbehavior is only bound by not resulting in UB from safe APIs and the crate-level encapsulation boundary of all of std, this makes writing user unsafe code that utilizes std theoretically impossible, as it now relies on undocumented QOI (quality of implementation) that unrelated parts of std cannot be caused to misbehave by a misuse of std::collections APIs. In practice, this is a nonconcern, because std has reasonable QOI and an implementation that takes advantage of this freedom is essentially a malicious implementation and only compliant by the most langauage-lawyer reading of the documentation. To close this hole, we just add a small clause to the existing logic error paragraph that ensures that any misbehavior is limited to the collection which observed the logic error, making it more plausible to prove the soundness of user unsafe code. This is not meant to be formal; a formal refinement would likely need to mention that values derived from the collection can also misbehave after a logic error is observed, as well as define what it means to "observe" a logic error in the first place. This fix errs on the side of informality in order to close the hole without complicating a normal reading which can assume a reasonable nonmalicious QOI. See also [discussion on IRLO][1]. [1]: https://internals.rust-lang.org/t/using-std-collections-and-unsafe-anything-can-happen/16640 r? rust-lang/libs-api ```@rustbot``` label +T-libs-api -T-libs This technically adds a new guarantee to the documentation, though I argue as written it's one already implicitly provided.
2 parents 0595ea1 + e6b1003 commit 4f4a819

File tree

5 files changed

+20
-17
lines changed

5 files changed

+20
-17
lines changed

Diff for: library/alloc/src/collections/binary_heap.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -166,9 +166,10 @@ mod tests;
166166
/// item's ordering relative to any other item, as determined by the [`Ord`]
167167
/// trait, changes while it is in the heap. This is normally only possible
168168
/// through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. The
169-
/// behavior resulting from such a logic error is not specified (it
170-
/// could include panics, incorrect results, aborts, memory leaks, or
171-
/// non-termination) but will not be undefined behavior.
169+
/// behavior resulting from such a logic error is not specified, but will
170+
/// be encapsulated to the `BinaryHeap` that observed the logic error and not
171+
/// result in undefined behavior. This could include panics, incorrect results,
172+
/// aborts, memory leaks, and non-termination.
172173
///
173174
/// # Examples
174175
///

Diff for: library/alloc/src/collections/btree/map.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
6464
/// It is a logic error for a key to be modified in such a way that the key's ordering relative to
6565
/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
6666
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
67-
/// The behavior resulting from such a logic error is not specified (it could include panics,
68-
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
69-
/// behavior.
67+
/// The behavior resulting from such a logic error is not specified, but will be encapsulated to the
68+
/// `BTreeMap` that observed the logic error and not result in undefined behavior. This could
69+
/// include panics, incorrect results, aborts, memory leaks, and non-termination.
7070
///
7171
/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::values`], or
7272
/// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and

Diff for: library/alloc/src/collections/btree/set.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ use super::Recover;
2323
/// It is a logic error for an item to be modified in such a way that the item's ordering relative
2424
/// to any other item, as determined by the [`Ord`] trait, changes while it is in the set. This is
2525
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
26-
/// The behavior resulting from such a logic error is not specified (it could include panics,
27-
/// incorrect results, aborts, memory leaks, or non-termination) but will not be undefined
28-
/// behavior.
26+
/// The behavior resulting from such a logic error is not specified, but will be encapsulated to the
27+
/// `BTreeSet` that observed the logic error and not result in undefined behavior. This could
28+
/// include panics, incorrect results, aborts, memory leaks, and non-termination.
2929
///
3030
/// Iterators returned by [`BTreeSet::iter`] produce their items in order, and take worst-case
3131
/// logarithmic and amortized constant time per item returned.

Diff for: library/std/src/collections/hash/map.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ use crate::sys;
5454
/// the [`Eq`] trait, changes while it is in the map. This is normally only
5555
/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
5656
/// The behavior resulting from such a logic error is not specified, but will
57-
/// not result in undefined behavior. This could include panics, incorrect results,
57+
/// be encapsulated to the `HashMap` that observed the logic error and not
58+
/// result in undefined behavior. This could include panics, incorrect results,
5859
/// aborts, memory leaks, and non-termination.
5960
///
6061
/// The hash table implementation is a Rust port of Google's [SwissTable].

Diff for: library/std/src/collections/hash/set.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ use super::map::{map_try_reserve_error, RandomState};
3333
/// In other words, if two keys are equal, their hashes must be equal.
3434
///
3535
///
36-
/// It is a logic error for an item to be modified in such a way that the
37-
/// item's hash, as determined by the [`Hash`] trait, or its equality, as
38-
/// determined by the [`Eq`] trait, changes while it is in the set. This is
39-
/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
40-
/// unsafe code. The behavior resulting from such a logic error is not
41-
/// specified (it could include panics, incorrect results, aborts, memory
42-
/// leaks, or non-termination) but will not be undefined behavior.
36+
/// It is a logic error for a key to be modified in such a way that the key's
37+
/// hash, as determined by the [`Hash`] trait, or its equality, as determined by
38+
/// the [`Eq`] trait, changes while it is in the map. This is normally only
39+
/// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
40+
/// The behavior resulting from such a logic error is not specified, but will
41+
/// be encapsulated to the `HashSet` that observed the logic error and not
42+
/// result in undefined behavior. This could include panics, incorrect results,
43+
/// aborts, memory leaks, and non-termination.
4344
///
4445
/// # Examples
4546
///

0 commit comments

Comments
 (0)