-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document that slices cannot be larger than isize::MAX
bytes
#53784
Changes from 3 commits
1975b8d
7b77508
1aac00f
5d9086f
11c6318
ebffb67
e370b1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,6 +34,7 @@ use cmp::Ordering::{self, Less, Equal, Greater}; | |
use cmp; | ||
use fmt; | ||
use intrinsics::assume; | ||
use isize; | ||
use iter::*; | ||
use ops::{FnMut, Try, self}; | ||
use option::Option; | ||
|
@@ -3851,6 +3852,9 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { | |
/// them from other data. You can obtain a pointer that is usable as `data` | ||
/// for zero-length slices using [`NonNull::dangling()`]. | ||
/// | ||
/// The total size of the slice must lower than `isize::MAX` **bytes** in | ||
/// memory. See the safety documentation of [`pointer::offset`]. | ||
/// | ||
/// # Caveat | ||
/// | ||
/// The lifetime for the returned slice is inferred from its usage. To | ||
|
@@ -3872,10 +3876,13 @@ unsafe impl<'a, T> TrustedRandomAccess for ExactChunksMut<'a, T> { | |
/// ``` | ||
/// | ||
/// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling | ||
/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset | ||
#[inline] | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { | ||
debug_assert!(data as usize % mem::align_of::<T>() == 0, "attempt to create unaligned slice"); | ||
debug_assert!(len * mem::size_of::<T>() < isize::MAX as usize, | ||
"attempt to create slice covering half the address space"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, since the docs phrase the restriction in bytes, maybe write the assertion that way? Perhaps debug_assert!(mem::size_of::<T>().saturating_mul(len) <= isize::MAX as usize); That handles ZSTs automatically and avoids non-obvious rounding code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this! |
||
Repr { raw: FatPtr { data, len } }.rust | ||
} | ||
|
||
|
@@ -3885,14 +3892,20 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { | |
/// This function is unsafe for the same reasons as [`from_raw_parts`], as well | ||
/// as not being able to provide a non-aliasing guarantee of the returned | ||
/// mutable slice. `data` must be non-null and aligned even for zero-length | ||
/// slices as with [`from_raw_parts`]. See the documentation of | ||
/// [`from_raw_parts`] for more details. | ||
/// slices as with [`from_raw_parts`]. The total size of the slice must be | ||
/// lower than `isize::MAX` **bytes** in memory. See the safety documentation | ||
/// of [`pointer::offset`]. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks a bit strange, with two "See ..." sentences right after one another. Also you made this new remark a new paragraph in the other method. Maybe remove the last sentence of this paragraph? Or else restore this paragraph to its original form, and add a new paragraph for the size limit. |
||
/// | ||
/// See the documentation of [`from_raw_parts`] for more details. | ||
/// | ||
/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html | ||
/// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset | ||
#[inline] | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { | ||
debug_assert!(data as usize % mem::align_of::<T>() == 0, "attempt to create unaligned slice"); | ||
debug_assert!(len * mem::size_of::<T>() < isize::MAX as usize, | ||
"attempt to create slice covering half the address space"); | ||
Repr { raw: FatPtr { data, len} }.rust_mut | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we sure that "exactly as large as half the address space" works correctly? That length (in bytes) does already not fit into a signed integer, so computing the address one-past-the-end (e.g. for iteration) would overflow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like it'd be best written as
len < isize::MAX as usize / mem::size_of::<T>()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@RalfJung True.
@ubsan I don't think this is clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tbu- not clearer, but it fixes overflow (and also happens at compile-time, as opposed to run-time)