-
Notifications
You must be signed in to change notification settings - Fork 13.2k
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
Guard against overflow in codemap::span_to_lines
.
#25013
Changes from all commits
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 |
---|---|---|
|
@@ -631,8 +631,14 @@ fn size_from_ptr<T>(_: *const T) -> usize { | |
} | ||
|
||
|
||
// Use macro to be generic over const/mut | ||
macro_rules! slice_offset { | ||
// Use macros to be generic over const/mut | ||
// | ||
// They require non-negative `$by` because otherwise the expression | ||
// `(ptr as usize + $by)` would interpret `-1` as `usize::MAX` (and | ||
// thus trigger a panic when overflow checks are on). | ||
|
||
// Use this to do `$ptr + $by`, where `$by` is non-negative. | ||
macro_rules! slice_add_offset { | ||
($ptr:expr, $by:expr) => {{ | ||
let ptr = $ptr; | ||
if size_from_ptr(ptr) == 0 { | ||
|
@@ -643,6 +649,18 @@ macro_rules! slice_offset { | |
}}; | ||
} | ||
|
||
// Use this to do `$ptr - $by`, where `$by` is non-negative. | ||
macro_rules! slice_sub_offset { | ||
($ptr:expr, $by:expr) => {{ | ||
let ptr = $ptr; | ||
if size_from_ptr(ptr) == 0 { | ||
transmute(ptr as usize - $by) | ||
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. GitHub seems to have lost my previous comment about this. It may have been a commit comment instead of a diff comment but I thought GitHub still preserved those. In the interests of making the discussion actually make sense, what I had suggested was that we don't need a separate macro at all, we just need wrapping arithmetic, like macro_rules! slice_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
transmute((ptr as isize).wrapping_add($by))
} else {
ptr.offset($by)
}
}};
} And FWIW I still believe this is the better approach. It more closely mimics the actual pointer arithmetic used for non-zero-sized types, it means none of the callers of the macro have to be updated, and it more closely matches the required changes for #25016 (I think we need to use wrapping addition in more places in this module in order to restore the pre-overflow-check behavior). 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 have kept the changes in the form presented here because I still believe this code is easier to read than that change that you suggest. (It is an entirely subjective opinion.) I freely admit that I have not done the full review of the For now, however, my main concern is getting |
||
} else { | ||
ptr.offset(-$by) | ||
} | ||
}}; | ||
} | ||
|
||
macro_rules! slice_ref { | ||
($ptr:expr) => {{ | ||
let ptr = $ptr; | ||
|
@@ -672,7 +690,7 @@ macro_rules! iterator { | |
None | ||
} else { | ||
let old = self.ptr; | ||
self.ptr = slice_offset!(self.ptr, 1); | ||
self.ptr = slice_add_offset!(self.ptr, 1); | ||
Some(slice_ref!(old)) | ||
} | ||
} | ||
|
@@ -714,7 +732,7 @@ macro_rules! iterator { | |
if self.end == self.ptr { | ||
None | ||
} else { | ||
self.end = slice_offset!(self.end, -1); | ||
self.end = slice_sub_offset!(self.end, 1); | ||
Some(slice_ref!(self.end)) | ||
} | ||
} | ||
|
@@ -816,7 +834,7 @@ impl<'a, T> Iter<'a, T> { | |
fn iter_nth(&mut self, n: usize) -> Option<&'a T> { | ||
match self.as_slice().get(n) { | ||
Some(elem_ref) => unsafe { | ||
self.ptr = slice_offset!(elem_ref as *const _, 1); | ||
self.ptr = slice_add_offset!(elem_ref as *const _, 1); | ||
Some(slice_ref!(elem_ref)) | ||
}, | ||
None => { | ||
|
@@ -959,7 +977,7 @@ impl<'a, T> IterMut<'a, T> { | |
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> { | ||
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) { | ||
Some(elem_ref) => unsafe { | ||
self.ptr = slice_offset!(elem_ref as *mut _, 1); | ||
self.ptr = slice_add_offset!(elem_ref as *mut _, 1); | ||
Some(slice_ref!(elem_ref)) | ||
}, | ||
None => { | ||
|
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.
Could you add a comment about why one can't just use
slice_offset!
/slice_add_offset!
with-1
?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.
will do.