diff options
| author | bors <bors@rust-lang.org> | 2015-05-07 15:25:09 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2015-05-07 15:25:09 +0000 |
| commit | a39d4fc68472ed7a512a7de93f422d7697d92e06 (patch) | |
| tree | fa4c4c0162d793699b5bae9bf7f8dc4ee5eafd40 /src/libcore | |
| parent | 05d5fcaa5ba0c385e1dc97037c89fae437634fc3 (diff) | |
| parent | 939e4c9ea9e63b4da1033d66a72a044279036e6f (diff) | |
| download | rust-a39d4fc68472ed7a512a7de93f422d7697d92e06.tar.gz rust-a39d4fc68472ed7a512a7de93f422d7697d92e06.zip | |
Auto merge of #25013 - pnkfelix:span_to_lines-oflo, r=huonw
Guard against overflow in `codemap::span_to_lines`. (Revised/expanded version of PR #24976) Make `span_to_lines` to return a `Result`. In `diagnostic`, catch `Err` from `span_to_lines` and print `"(unprintable span)"` instead. ---- There a number of recent issues that report the bug here. See e.g. #24761 and #24954. This change *might* fix them. However, that is *not* its main goal. The main goals are: 1. Make it possible for callers to recover from an error here, and 2. Insert a more conservative check, in that we are also checking that the files match up. ---- As a drive-by, fix #24997 , which was causing my attempts to `make check-stage1` on an `--enable-debug` build to fail.
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/slice.rs | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index f0accef92ce..56dee303487 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -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) + } 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)) } } @@ -776,7 +794,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 => { @@ -849,7 +867,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 => { |
