about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-04-02 14:28:03 +0200
committerGitHub <noreply@github.com>2020-04-02 14:28:03 +0200
commitec0da7222d04862de8c822e106522ef448d85b6d (patch)
tree74b275beb0c7580977630c49f8243d344132fe00
parentc10f214ddcc5acea281b05b9f6f43543c91024f9 (diff)
parentf543689eb65aeacb6ec85c07f0c82800174d21c1 (diff)
downloadrust-ec0da7222d04862de8c822e106522ef448d85b6d.tar.gz
rust-ec0da7222d04862de8c822e106522ef448d85b6d.zip
Rollup merge of #70681 - rcoh:russell/70677-raw-str-panic, r=petrochenkov
Handle unterminated raw strings with no #s properly

The modified code to handle parsing raw strings didn't properly account for the case where there was no "#" on either end and erroneously reported this strings as complete. This lead to a panic trying to read off the end of the file.

Fixes #70677

r? @petrochenkov

cc @Centril
-rw-r--r--src/librustc_lexer/src/lib.rs9
-rw-r--r--src/librustc_lexer/src/tests.rs27
-rw-r--r--src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs5
-rw-r--r--src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr9
4 files changed, 49 insertions, 1 deletions
diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs
index fcb7475cc2e..5ccfc1b276b 100644
--- a/src/librustc_lexer/src/lib.rs
+++ b/src/librustc_lexer/src/lib.rs
@@ -148,6 +148,10 @@ pub enum LiteralKind {
 pub struct UnvalidatedRawStr {
     /// The prefix (`r###"`) is valid
     valid_start: bool,
+
+    /// The postfix (`"###`) is valid
+    valid_end: bool,
+
     /// The number of leading `#`
     n_start_hashes: usize,
     /// The number of trailing `#`. `n_end_hashes` <= `n_start_hashes`
@@ -197,7 +201,7 @@ impl UnvalidatedRawStr {
         let n_start_safe: u16 =
             self.n_start_hashes.try_into().map_err(|_| LexRawStrError::TooManyDelimiters)?;
 
-        if self.n_start_hashes > self.n_end_hashes {
+        if self.n_start_hashes > self.n_end_hashes || !self.valid_end {
             Err(LexRawStrError::NoTerminator {
                 expected: self.n_start_hashes,
                 found: self.n_end_hashes,
@@ -687,6 +691,7 @@ impl Cursor<'_> {
             _ => {
                 return UnvalidatedRawStr {
                     valid_start,
+                    valid_end: false,
                     n_start_hashes,
                     n_end_hashes: 0,
                     possible_terminator_offset,
@@ -702,6 +707,7 @@ impl Cursor<'_> {
             if self.is_eof() {
                 return UnvalidatedRawStr {
                     valid_start,
+                    valid_end: false,
                     n_start_hashes,
                     n_end_hashes: max_hashes,
                     possible_terminator_offset,
@@ -727,6 +733,7 @@ impl Cursor<'_> {
             if n_end_hashes == n_start_hashes {
                 return UnvalidatedRawStr {
                     valid_start,
+                    valid_end: true,
                     n_start_hashes,
                     n_end_hashes,
                     possible_terminator_offset: None,
diff --git a/src/librustc_lexer/src/tests.rs b/src/librustc_lexer/src/tests.rs
index 4af435536f0..06fc159fe25 100644
--- a/src/librustc_lexer/src/tests.rs
+++ b/src/librustc_lexer/src/tests.rs
@@ -23,6 +23,7 @@ mod tests {
                 n_start_hashes: 0,
                 n_end_hashes: 0,
                 valid_start: true,
+                valid_end: true,
                 possible_terminator_offset: None,
             },
             Ok(ValidatedRawStr { n_hashes: 0 }),
@@ -37,6 +38,7 @@ mod tests {
                 n_start_hashes: 0,
                 n_end_hashes: 0,
                 valid_start: true,
+                valid_end: true,
                 possible_terminator_offset: None,
             },
             Ok(ValidatedRawStr { n_hashes: 0 }),
@@ -51,6 +53,7 @@ mod tests {
             UnvalidatedRawStr {
                 n_start_hashes: 1,
                 n_end_hashes: 1,
+                valid_end: true,
                 valid_start: true,
                 possible_terminator_offset: None,
             },
@@ -65,6 +68,7 @@ mod tests {
             UnvalidatedRawStr {
                 n_start_hashes: 1,
                 n_end_hashes: 0,
+                valid_end: false,
                 valid_start: true,
                 possible_terminator_offset: None,
             },
@@ -80,6 +84,7 @@ mod tests {
                 n_start_hashes: 2,
                 n_end_hashes: 1,
                 valid_start: true,
+                valid_end: false,
                 possible_terminator_offset: Some(7),
             },
             Err(LexRawStrError::NoTerminator {
@@ -95,6 +100,7 @@ mod tests {
                 n_start_hashes: 2,
                 n_end_hashes: 0,
                 valid_start: true,
+                valid_end: false,
                 possible_terminator_offset: None,
             },
             Err(LexRawStrError::NoTerminator {
@@ -113,9 +119,30 @@ mod tests {
                 n_start_hashes: 1,
                 n_end_hashes: 0,
                 valid_start: false,
+                valid_end: false,
                 possible_terminator_offset: None,
             },
             Err(LexRawStrError::InvalidStarter),
         );
     }
+
+    #[test]
+    fn test_unterminated_no_pound() {
+        // https://github.com/rust-lang/rust/issues/70677
+        check_raw_str(
+            r#"""#,
+            UnvalidatedRawStr {
+                n_start_hashes: 0,
+                n_end_hashes: 0,
+                valid_start: true,
+                valid_end: false,
+                possible_terminator_offset: None,
+            },
+            Err(LexRawStrError::NoTerminator {
+                expected: 0,
+                found: 0,
+                possible_terminator_offset: None,
+            }),
+        );
+    }
 }
diff --git a/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs
new file mode 100644
index 00000000000..bdfc29a3d57
--- /dev/null
+++ b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.rs
@@ -0,0 +1,5 @@
+// This won't actually panic because of the error comment -- the `"` needs to be
+// the last byte in the file (including not having a trailing newline)
+// Prior to the fix you get the error: 'expected item, found `r" ...`'
+// because the string being unterminated wasn't properly detected.
+r" //~ unterminated raw string
diff --git a/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr
new file mode 100644
index 00000000000..3a7e2a4b14a
--- /dev/null
+++ b/src/test/ui/parser/raw/issue-70677-panic-on-unterminated-raw-str-at-eof.stderr
@@ -0,0 +1,9 @@
+error[E0748]: unterminated raw string
+  --> $DIR/issue-70677-panic-on-unterminated-raw-str-at-eof.rs:5:1
+   |
+LL | r"
+   | ^ unterminated raw string
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0748`.