about summary refs log tree commit diff
path: root/src/libsyntax/codemap.rs
diff options
context:
space:
mode:
authorRyan Cumming <etaoins@gmail.com>2018-02-25 11:41:08 +1100
committerRyan Cumming <etaoins@gmail.com>2018-02-25 11:41:08 +1100
commitd27fac618d0e9e054fbc65130788eaacda259a9f (patch)
treec00b5ba3bbd4ab1f75df79a0a03f7f84e6b9c4de /src/libsyntax/codemap.rs
parent6070d3e47e5e9f15575a3bd33583358b52bc6eda (diff)
downloadrust-d27fac618d0e9e054fbc65130788eaacda259a9f.tar.gz
rust-d27fac618d0e9e054fbc65130788eaacda259a9f.zip
Fix find_width_of_character_at_span bounds check
Commit 0bd96671f0 added bounds checking of our current target byte
position to prevent infinite loops. Unfortunately it was comparing the
file-relative `target` versus the global relative `file_start_pos` and
`file_end_pos`.

The result is failing to detect multibyte characters unless their
file-relative offset fit within their global offset. This causes other
parts of the compiler to generate spans pointing to the middle of a
multibyte character which will ultimately panic in
`bytepos_to_file_charpos`.

Fix by comparing the `target` to the total file size when moving forward
and doing checked subtraction when moving backwards. This should
preserve the intent of the bounds check while removing the offset
confusion.

Fixes #48508
Diffstat (limited to 'src/libsyntax/codemap.rs')
-rw-r--r--src/libsyntax/codemap.rs19
1 files changed, 11 insertions, 8 deletions
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index df5845f6c21..5d36f39b2e4 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -705,17 +705,20 @@ impl CodeMap {
         };
         debug!("find_width_of_character_at_span: snippet=`{:?}`", snippet);
 
-        let file_start_pos = local_begin.fm.start_pos.to_usize();
-        let file_end_pos = local_begin.fm.end_pos.to_usize();
-        debug!("find_width_of_character_at_span: file_start_pos=`{:?}` file_end_pos=`{:?}`",
-               file_start_pos, file_end_pos);
-
         let mut target = if forwards { end_index + 1 } else { end_index - 1 };
         debug!("find_width_of_character_at_span: initial target=`{:?}`", target);
 
-        while !snippet.is_char_boundary(target - start_index)
-                && target >= file_start_pos && target <= file_end_pos {
-            target = if forwards { target + 1 } else { target - 1 };
+        while !snippet.is_char_boundary(target - start_index) && target < source_len {
+            target = if forwards {
+                target + 1
+            } else {
+                match target.checked_sub(1) {
+                    Some(target) => target,
+                    None => {
+                        break;
+                    }
+                }
+            };
             debug!("find_width_of_character_at_span: target=`{:?}`", target);
         }
         debug!("find_width_of_character_at_span: final target=`{:?}`", target);