mirror of
https://github.com/zensical/zensical.git
synced 2026-08-23 15:46:44 +00:00
fix: harden link validation for files with CRLF line endings
Signed-off-by: squidfunk <martin.donath@squidfunk.com>
This commit is contained in:
@@ -569,8 +569,15 @@ class TestLinkDefinitions:
|
||||
assert text(md, link_defs[0].id) == expected_id
|
||||
assert text(md, link_defs[0].href) == expected_href
|
||||
|
||||
def test_link_def_title_on_next_line(self) -> None:
|
||||
md = b'[id]: href\n "Title"'
|
||||
@pytest.mark.parametrize(
|
||||
"md",
|
||||
[
|
||||
pytest.param(b'[id]: href\n "Title"', id="lf"),
|
||||
pytest.param(b'[id]: href\r\n "Title"', id="crlf"),
|
||||
pytest.param(b'[id]: href\r "Title"', id="cr"),
|
||||
],
|
||||
)
|
||||
def test_link_def_title_on_next_line(self, md: bytes) -> None:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 1
|
||||
|
||||
@@ -579,6 +586,34 @@ class TestLinkDefinitions:
|
||||
assert text(md, link_defs[0].id) == b"id"
|
||||
assert text(md, link_defs[0].href) == b"href"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"md",
|
||||
[
|
||||
pytest.param(
|
||||
b"[id]: <href>\r\n[after](href)",
|
||||
id="crlf",
|
||||
),
|
||||
pytest.param(
|
||||
b"[id]: <href>\r[after](href)",
|
||||
id="cr",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_link_def_angle_brackets_with_link_after(
|
||||
self, md: bytes
|
||||
) -> None:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 2
|
||||
|
||||
link_defs = link_defs_only(refs)
|
||||
assert len(link_defs) == 1
|
||||
assert text(md, link_defs[0].id) == b"id"
|
||||
assert text(md, link_defs[0].href) == b"href"
|
||||
|
||||
links = links_only(refs)
|
||||
assert len(links) == 1
|
||||
assert text(md, links[0].text) == b"after"
|
||||
|
||||
# --- negative cases ---
|
||||
|
||||
def test_no_link_def_empty_href(self) -> None:
|
||||
@@ -1205,6 +1240,18 @@ class TestWikilinks:
|
||||
b"id",
|
||||
id="link-ref-with-newline",
|
||||
),
|
||||
pytest.param(
|
||||
b"[[Page]]\r\n[id]",
|
||||
b"[Page]",
|
||||
b"id",
|
||||
id="link-ref-with-crlf",
|
||||
),
|
||||
pytest.param(
|
||||
b"[[Page]]\r[id]",
|
||||
b"[Page]",
|
||||
b"id",
|
||||
id="link-ref-with-cr",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_no_wikilink(
|
||||
@@ -1478,6 +1525,10 @@ class TestFencedCodeBlocks:
|
||||
b"```\r\n[Start]\r\n```\r\n",
|
||||
id="fenced-code-crlf-with-shortcut-link-ref",
|
||||
),
|
||||
pytest.param(
|
||||
b"```\r[Start]\r```\r",
|
||||
id="fenced-code-cr-with-shortcut-link-ref",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_fenced_code(self, md: bytes) -> None:
|
||||
@@ -1646,6 +1697,14 @@ class TestMath:
|
||||
b"\\[\n[text](href)\n\\]",
|
||||
id="match-block-brackets",
|
||||
),
|
||||
pytest.param(
|
||||
b"\\[\r\n[text](href)\r\n\\]",
|
||||
id="match-block-brackets-crlf",
|
||||
),
|
||||
pytest.param(
|
||||
b"\\[\r[text](href)\r\\]",
|
||||
id="match-block-brackets-cr",
|
||||
),
|
||||
pytest.param(
|
||||
b"\\[ [text](href) \\]",
|
||||
id="match-block-brackets, single line",
|
||||
@@ -1685,6 +1744,22 @@ class TestMath:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 0
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"md",
|
||||
[
|
||||
pytest.param(b"$[text](href)\n$", id="lf"),
|
||||
pytest.param(b"$[text](href)\r\n$", id="crlf"),
|
||||
pytest.param(b"$[text](href)\r$", id="cr"),
|
||||
],
|
||||
)
|
||||
def test_no_math_inline_across_line_ending(self, md: bytes) -> None:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 1
|
||||
|
||||
links = links_only(refs)
|
||||
assert len(links) == 1
|
||||
assert text(md, links[0].text) == b"text"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1705,6 +1780,16 @@ class TestHtmlLinks:
|
||||
b"href",
|
||||
id="html-a-href, in block",
|
||||
),
|
||||
pytest.param(
|
||||
b'<div>\r\n<a href="href">text</a>\r\n</div>',
|
||||
b"href",
|
||||
id="html-a-href, in block, crlf",
|
||||
),
|
||||
pytest.param(
|
||||
b'<div>\r<a href="href">text</a>\r</div>',
|
||||
b"href",
|
||||
id="html-a-href, in block, cr",
|
||||
),
|
||||
pytest.param(
|
||||
b'<img src="image.png">',
|
||||
b"image.png",
|
||||
@@ -1911,6 +1996,14 @@ class TestJinja:
|
||||
b"{% if [text](href) %}...{% endif %}",
|
||||
id="jinja-block",
|
||||
),
|
||||
pytest.param(
|
||||
b"{% if\r\n[text](href)\r\n%}",
|
||||
id="jinja-block-crlf",
|
||||
),
|
||||
pytest.param(
|
||||
b"{% if\r[text](href)\r%}",
|
||||
id="jinja-block-cr",
|
||||
),
|
||||
pytest.param(
|
||||
b"{{ [text](href) }}",
|
||||
id="jinja-expr",
|
||||
@@ -1925,6 +2018,22 @@ class TestJinja:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 0
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"md",
|
||||
[
|
||||
pytest.param(b"{% if\n\n[text](href) %}", id="lf"),
|
||||
pytest.param(b"{% if\r\n\r\n[text](href) %}", id="crlf"),
|
||||
pytest.param(b"{% if\r\r[text](href) %}", id="cr"),
|
||||
],
|
||||
)
|
||||
def test_refs_after_jinja_blank_line(self, md: bytes) -> None:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 1
|
||||
|
||||
links = links_only(refs)
|
||||
assert len(links) == 1
|
||||
assert text(md, links[0].text) == b"text"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -1932,11 +2041,39 @@ class TestJinja:
|
||||
class TestExclusions:
|
||||
"""Tests for further exclusions."""
|
||||
|
||||
def test_abbreviations(self) -> None:
|
||||
md = b"*[abbr]: text\n"
|
||||
@pytest.mark.parametrize(
|
||||
"md",
|
||||
[
|
||||
pytest.param(b"*[abbr]: text\n", id="lf"),
|
||||
pytest.param(b"*[abbr]: text\r\n", id="crlf"),
|
||||
pytest.param(b"*[abbr]: text\r", id="cr"),
|
||||
],
|
||||
)
|
||||
def test_abbreviations(self, md: bytes) -> None:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 0
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"md",
|
||||
[
|
||||
pytest.param(
|
||||
b"*[abbr]: text\r\n[after](href)",
|
||||
id="crlf",
|
||||
),
|
||||
pytest.param(
|
||||
b"*[abbr]: text\r[after](href)",
|
||||
id="cr",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_abbreviation_with_link_after(self, md: bytes) -> None:
|
||||
refs = collect(md)
|
||||
assert len(refs) == 1
|
||||
|
||||
links = links_only(refs)
|
||||
assert len(links) == 1
|
||||
assert text(md, links[0].text) == b"after"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"md",
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user