]> git.lizzy.rs Git - rust.git/commitdiff
don't ICE on large files
authorAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 17 Jun 2019 08:35:26 +0000 (11:35 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 17 Jun 2019 16:34:47 +0000 (19:34 +0300)
This is an extremely marginal error, so the cost of properly threading
`Handler` everywhere just not seemed justified. However, it's useful
to panic when we create a file, and not when we slice strings with
overflown indexes somewhere in the guts of the compiler.

For this reason, while we provide safe `try_new_source_file`, we don't
change the existing public interface and just panic more or less
cleanly.

src/libsyntax/source_map.rs
src/libsyntax_pos/lib.rs

index a21d2df416206fc3c44534800ea3d2ff79d7a070..c0307263387ec6c7e8ec034f33da873f8ad40b8f 100644 (file)
@@ -191,6 +191,18 @@ fn next_start_pos(&self) -> usize {
     /// If a file already exists in the source_map with the same id, that file is returned
     /// unmodified
     pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile> {
+        self.try_new_source_file(filename, src)
+            .unwrap_or_else(|OffsetOverflowError| {
+                eprintln!("fatal error: rustc does not support files larger than 4GB");
+                errors::FatalError.raise()
+            })
+    }
+
+    fn try_new_source_file(
+        &self,
+        filename: FileName,
+        src: String
+    ) -> Result<Lrc<SourceFile>, OffsetOverflowError> {
         let start_pos = self.next_start_pos();
 
         // The path is used to determine the directory for loading submodules and
@@ -212,7 +224,7 @@ pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile
                                                        was_remapped,
                                                        Some(&unmapped_path));
 
-        return match self.source_file_by_stable_id(file_id) {
+        let lrc_sf = match self.source_file_by_stable_id(file_id) {
             Some(lrc_sf) => lrc_sf,
             None => {
                 let source_file = Lrc::new(SourceFile::new(
@@ -221,7 +233,7 @@ pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile
                     unmapped_path,
                     src,
                     Pos::from_usize(start_pos),
-                ));
+                )?);
 
                 let mut files = self.files.borrow_mut();
 
@@ -230,7 +242,8 @@ pub fn new_source_file(&self, filename: FileName, src: String) -> Lrc<SourceFile
 
                 source_file
             }
-        }
+        };
+        Ok(lrc_sf)
     }
 
     /// Allocates a new SourceFile representing a source file from an external
index e7158372762dd99dba0c5f8c4594c5ce0505d4cc..2dd409bf5bee09b86a734bd60b881b7dcbd72993 100644 (file)
@@ -859,6 +859,9 @@ pub fn get_source(&self) -> Option<&str> {
     }
 }
 
+#[derive(Debug)]
+pub struct OffsetOverflowError;
+
 /// A single source in the `SourceMap`.
 #[derive(Clone)]
 pub struct SourceFile {
@@ -1040,7 +1043,7 @@ pub fn new(name: FileName,
                name_was_remapped: bool,
                unmapped_path: FileName,
                mut src: String,
-               start_pos: BytePos) -> SourceFile {
+               start_pos: BytePos) -> Result<SourceFile, OffsetOverflowError> {
         remove_bom(&mut src);
 
         let src_hash = {
@@ -1054,11 +1057,14 @@ pub fn new(name: FileName,
             hasher.finish()
         };
         let end_pos = start_pos.to_usize() + src.len();
+        if end_pos > u32::max_value() as usize {
+            return Err(OffsetOverflowError);
+        }
 
         let (lines, multibyte_chars, non_narrow_chars) =
             analyze_source_file::analyze_source_file(&src[..], start_pos);
 
-        SourceFile {
+        Ok(SourceFile {
             name,
             name_was_remapped,
             unmapped_path: Some(unmapped_path),
@@ -1072,7 +1078,7 @@ pub fn new(name: FileName,
             multibyte_chars,
             non_narrow_chars,
             name_hash,
-        }
+        })
     }
 
     /// Returns the `BytePos` of the beginning of the current line.