Repository: raphlinus/pulldown-cmark (rust)

Issue:
[fuzz result] backslash escapes in link def prevent paragraph breaks
Consider this markdown:

```markdown
[x\

]: https://rust-lang.org
```

That's not a link definition, but pulldown-cmark thinks it is. The hard line break on line 1 is an inline element, and should not prevent the paragraph break from parsing.

<details>

Events from pulldown-cmark:

```rust
"[\\\n\n]:l\n" -> [
]
```

Events from pandoc:

```rust
"[\\\n\n]:l\n" -> [
  Start(Paragraph)
    Text(Boxed("[\\"))
  End(Paragraph)
  Start(Paragraph)
    Text(Boxed("]:l"))
  End(Paragraph)
]
```

Events from commonmark.js:

```rust
"[\\\n\n]:l\n" -> [
  Start(Paragraph)
    Text(Boxed("[\\"))
  End(Paragraph)
  Start(Paragraph)
    Text(Boxed("]:l"))
  End(Paragraph)
]
```

AST from [pandoc](https://pandoc.org/try/?params=%7B%22text%22%3A%22%5B%5C%5C%5Cn%5Cn%5D%3Al%5Cn%22%2C%22to%22%3A%22json%22%2C%22from%22%3A%22commonmark%22%7D):

```text
Pandoc {
    meta: {},
    blocks: [
        Para(
            [
                Str(
                    "[\\",
                ),
            ],
        ),
        Para(
            [
                Str(
                    "]:l",
                ),
            ],
        ),
    ],
}
```

Pull request:
Do not parse hard line breaks when doing link label blocks
Fixes #753

Consider this markdown:

```markdown
[x\

]: https://rust-lang.org
```

That's not a link definition, but pulldown-cmark thought it was. The hard line break on line 1 is an inline element, and should not prevent the paragraph break from parsing.

Patch:
diff --git a/specs/regression.txt b/specs/regression.txt
index 95856fa..566adbc 100644
--- a/specs/regression.txt
+++ b/specs/regression.txt
@@ -1511,6 +1511,7 @@ _*xx-_-
 <p><em>*xx-</em>-</p>
 ````````````````````````````````
 
+
 ISSUE 751
 
 ```````````````````````````````` example
@@ -1562,3 +1563,14 @@ ISSUE 751
 </li>
 </ul>
 ````````````````````````````````
+
+ISSUE 753
+
+```````````````````````````````` example
+[x\
+
+]: https://rust-lang.org
+.
+<p>[x\</p>
+<p>]: https://rust-lang.org</p>
+````````````````````````````````
diff --git a/src/linklabel.rs b/src/linklabel.rs
index 9c588ef..83f0ecc 100644
--- a/src/linklabel.rs
+++ b/src/linklabel.rs
@@ -22,7 +22,7 @@
 
 use unicase::UniCase;
 
-use crate::scanners::{is_ascii_whitespace, scan_eol};
+use crate::scanners::{is_ascii_whitespace, scan_eol, is_ascii_punctuation};
 use crate::strings::CowStr;
 
 #[derive(Debug)]
@@ -60,7 +60,7 @@ pub(crate) fn scan_link_label_rest<'t>(
         match *bytes.get(ix)? {
             b'[' => return None,
             b']' => break,
-            b'\\' => {
+            b'\\' if is_ascii_punctuation(*bytes.get(ix + 1)?) => {
                 ix += 2;
                 codepoints += 2;
                 only_white_space = false;


Test patch:
diff --git a/tests/suite/regression.rs b/tests/suite/regression.rs
index dce6df2..5ef5d42 100644
--- a/tests/suite/regression.rs
+++ b/tests/suite/regression.rs
@@ -1840,3 +1840,16 @@ fn regression_test_118() {
 
     test_markdown_html(original, expected, false, false, false);
 }
+
+#[test]
+fn regression_test_119() {
+    let original = r##"[x\
+
+]: https://rust-lang.org
+"##;
+    let expected = r##"<p>[x\</p>
+<p>]: https://rust-lang.org</p>
+"##;
+  
+    test_markdown_html(original, expected, false, false, false);
+}