Repository: raphlinus/pulldown-cmark (rust)

Issue:
[fuzz result]: Incorrect match nesting when an unmatched delimiter is flanked by other delimiters
Notice the very counterintuitive behavior where `_x_\n*{*{` recognizes the last two asterisks as delimiters, but if the `x` is turned into an asterisk, they stop being recognized.

Events from pulldown-cmark:

```rust
"_*_\n*{*{\n" -> [
  Start(Paragraph)
    Start(Emphasis)
      Text(Borrowed("*"))
    End(Emphasis)
    SoftBreak
    Text(Boxed("*{*{"))
  End(Paragraph)
]
```

Events from pandoc:

```rust
"_*_\n*{*{\n" -> [
  Start(Paragraph)
    Start(Emphasis)
      Text(Boxed("*"))
    End(Emphasis)
    SoftBreak
    Start(Emphasis)
      Text(Boxed("{"))
    End(Emphasis)
    Text(Boxed("{"))
  End(Paragraph)
]
```

Events from commonmark.js:

```rust
"_*_\n*{*{\n" -> [
  Start(Paragraph)
    Start(Emphasis)
      Text(Boxed("*"))
    End(Emphasis)
    SoftBreak
    Start(Emphasis)
      Text(Boxed("{"))
    End(Emphasis)
    Text(Boxed("{"))
  End(Paragraph)
]
```

AST from [pandoc](https://pandoc.org/try/?params=%7B%22text%22%3A%22_%2A_%5Cn%2A%7B%2A%7B%5Cn%22%2C%22to%22%3A%22json%22%2C%22from%22%3A%22commonmark%22%7D):

```text
Pandoc {
    meta: {},
    blocks: [
        Para(
            [
                Emph(
                    [
                        Str(
                            "*",
                        ),
                    ],
                ),
                SoftBreak,
                Emph(
                    [
                        Str(
                            "{",
                        ),
                    ],
                ),
                Str(
                    "{",
                ),
            ],
        ),
    ],
}
```


Pull request description:
Fix emphasis stack truncation bug
Fixes #739

Patch:
diff --git a/specs/regression.txt b/specs/regression.txt
index 6c77577..2ecd229 100644
--- a/specs/regression.txt
+++ b/specs/regression.txt
@@ -1465,3 +1465,23 @@ ISSUE 737
 <p>[x] is not a valid link definition, because parens aren't balanced.</p>
 <p>[x]: (</p>
 ````````````````````````````````
+
+ISSUE 739
+
+```````````````````````````````` example
+Both of these two paragraphs are structurally the same, but the first one has
+an unmatched asterisk.
+
+_*_
+*{*{
+
+_x_
+*{*{
+.
+<p>Both of these two paragraphs are structurally the same, but the first one has
+an unmatched asterisk.</p>
+<p><em>*</em>
+<em>{</em>{</p>
+<p><em>x</em>
+<em>{</em>{</p>
+````````````````````````````````
\ No newline at end of file
diff --git a/src/parse.rs b/src/parse.rs
index 6c08743..167acdf 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -1103,6 +1103,15 @@ impl InlineStack {
         }
     }
 
+    fn truncate(&mut self, new_bound: usize) {
+        self.stack.truncate(new_bound);
+        for lower_bound in &mut self.lower_bounds {
+            if *lower_bound > new_bound {
+                *lower_bound = new_bound;
+            }
+        }
+    }
+
     fn find_match(
         &mut self,
         tree: &mut Tree<Item>,
@@ -1127,7 +1136,7 @@ impl InlineStack {
                     tree[el.start + i].item.body = ItemBody::Text;
                 }
             }
-            self.stack.truncate(matching_ix);
+            self.truncate(matching_ix);
             Some(matching_el)
         } else {
             self.set_lowerbound(c, count, both, self.stack.len());


Test patch:
diff --git a/tests/suite/regression.rs b/tests/suite/regression.rs
index 40d4f17..f844ff5 100644
--- a/tests/suite/regression.rs
+++ b/tests/suite/regression.rs
@@ -1731,3 +1731,25 @@ fn regression_test_113() {
 
     test_markdown_html(original, expected, false, false, false);
 }
+
+#[test]
+fn regression_test_114() {
+    let original = r##"Both of these two paragraphs are structurally the same, but the first one has
+an unmatched asterisk.
+
+_*_
+*{*{
+
+_x_
+*{*{
+"##;
+    let expected = r##"<p>Both of these two paragraphs are structurally the same, but the first one has
+an unmatched asterisk.</p>
+<p><em>*</em>
+<em>{</em>{</p>
+<p><em>x</em>
+<em>{</em>{</p>
+"##;
+  
+    test_markdown_html(original, expected, false, false, false);
+}
\ No newline at end of file