Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

- Fix a potential security issue in the URL escaping logic of the Markdown renderer.
- Fix GFM table indentation in list.
- Fix an infinite loop caused by unnormalized line breaks.

## v2.2.2(2026-01-05)

Expand Down
6 changes: 4 additions & 2 deletions marko/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@


def _preprocess_text(text: str) -> str:
return text.replace("\r\n", "\n")
# Normalize line terminators so block parsers can always advance on line reads.
return text.replace("\r\n", "\n").replace("\r", "\n").replace("\f", "\n")


class Source:
Expand Down Expand Up @@ -102,7 +103,8 @@ def expect_re(self, regexp: Pattern[str] | str) -> Match[str] | None:
:returns: the match object.
"""
prefix_len = self.match_prefix(
self.prefix, self.next_line(require_prefix=False) # type: ignore
self.prefix,
self.next_line(require_prefix=False), # type: ignore
)
if prefix_len >= 0:
match = self._expect_re(regexp, self.pos + prefix_len)
Expand Down
7 changes: 5 additions & 2 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@
import re
import textwrap

from marko.source import Source
import pytest

import marko
from marko import block
from marko.ast_renderer import ASTRenderer, XMLRenderer
from marko.md_renderer import MarkdownRenderer
from marko.source import Source
from tests.normalize import normalize_html


class TestBasic:
@pytest.mark.parametrize("text", ["-\r-", "-\f-"])
def test_non_lf_line_terminators_no_infinite_loop(self, text):
assert marko.convert(text) == marko.convert("-\n-")

def test_xml_renderer(self):
text = "[Overview](#overview)\n\n* * *"
markdown = marko.Markdown(renderer=XMLRenderer)
Expand Down Expand Up @@ -169,7 +173,6 @@ class CustomElement(block.BlockElement):
def __init__(self, match: re.Match[str]) -> None:
self.inline_body = match.group(1).strip()


@classmethod
def match(cls, source: Source) -> "re.Match[str] | None":
return source.expect_re(cls.pattern)
Expand Down
Loading