Repository: fancy-regex/fancy-regex (language: rust)

Issue:
Panic on not common input
Hi! Thank you for this library!

While fuzzing the [jsonschema](https://github.com/Stranger6667/jsonschema-rs/issues/253) crate, I found that `fancy-regex` panics on `\\u` (and a few more similar patterns like `\\U` and `\\x`), with:

```
thread 'main' panicked at 'index out of bounds: the len is 2 but the index is 2', /home/stranger6667/.cargo/registry/src/github.com-1ecc6299db9ec823/fancy-regex-0.6.0/src/parse.rs:394:17
```

**Code to reproduce**:

```rust
fn main() {
    fancy_regex::Regex::new("\\u");
}
```

Though it is an incomplete escape sequence, it will be nice to return `Err` in such cases as in `regex`:

```
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
regex parse error:
    \u
      ^
error: incomplete escape sequence, reached end of pattern prematurely
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

Probably, the solution will be to check the bounds before going to `bytes[ix]` inside `Parser::parse_hex`.
Let me know what do you think, I'll be happy to submit a PR to fix this :)


Discussion / hints:
Oh nice, thanks for doing that :)! Yeah the fix sounds good, looking forward to the PR.

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 17268ff..034ebe5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
 This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html),
 with the exception that 0.x versions can break between minor versions.
 
+### Fixed
+
+- Panic on incomplete escape sequences in input regexes
+
 ## [0.7.0] - 2021-07-12
 ### Added
 - `Regex` now has replace methods like the regex crate:
diff --git a/src/parse.rs b/src/parse.rs
index 23e818a..298844d 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -390,6 +390,10 @@ impl<'a> Parser<'a> {
 
     // ix points after '\x', eg to 'A0' or '{12345}', or after `\u` or `\U`
     fn parse_hex(&self, ix: usize, digits: usize) -> Result<(usize, Expr)> {
+        if ix >= self.re.len() {
+            // Incomplete escape sequence
+            return Err(Error::InvalidHex);
+        }
         let bytes = self.re.as_bytes();
         let b = bytes[ix];
         let (end, s) = if ix + digits <= self.re.len()


Test patch:
diff --git a/tests/finding.rs b/tests/finding.rs
index a907aaa..b92bf87 100644
--- a/tests/finding.rs
+++ b/tests/finding.rs
@@ -224,3 +224,11 @@ fn find_match<'t>(re: &str, text: &'t str) -> Option<Match<'t>> {
     );
     result.unwrap()
 }
+
+#[test]
+fn incomplete_escape_sequences() {
+    // See GH-76
+    assert!(Regex::new("\\u").is_err());
+    assert!(Regex::new("\\U").is_err());
+    assert!(Regex::new("\\x").is_err());
+}