Skip to content

Reject link destinations with unbalanced parentheses - #294

Merged
frostming merged 2 commits into
frostming:masterfrom
Enesuygurs:fix/unbalanced-parens-link-destination
Nov 9, 2026
Merged

frostming merged 2 commits into
frostming:masterfrom
Enesuygurs:fix/unbalanced-parens-link-destination

Conversation

@Enesuygurs

Copy link
Copy Markdown
Contributor

A link destination that isn't wrapped in <...> may only contain parentheses that are backslash-escaped or part of a balanced pair (spec §6.3; link reference definitions use the same rule, §4.7). _parse_link_dest_title counted open parentheses but never checked that they were all closed when the destination ended at whitespace or at the end of the input. As a result:

  • [a]: /u( was accepted as a link reference definition. The line disappeared from the output, and [a] elsewhere became a link to /u(.
  • [a](/u( "t") was rendered as a link with a title.
>>> marko.convert("[a]: /u(\n\n[a]")
'<p><a href="/u(">a</a></p>\n'          # before
'<p>[a]: /u(</p>\n<p>[a]</p>\n'         # after

Both are now left as plain text, which matches cmark, commonmark.js and markdown-it. Balanced cases such as [a](foo(and(bar))) still produce links.

The bundled spec examples only cover an unclosed parenthesis that runs up to the closing ), which is why the existing tests didn't catch this. I added regression tests for the reference definition and the inline case. They fail without the change, and the full test suite passes.

@human-attestation

Copy link
Copy Markdown

🛡️ Human Attestation required. A human needs to confirm this PR once before it can merge.

Attest this PR — sign in with GitHub, pass the challenge, and confirm one of the statements.

@frostming

Copy link
Copy Markdown
Owner

@Enesuygurs please resolve conflicts

…rens-link-destination

# Conflicts:
#	tests/test_basic.py
@Enesuygurs

Copy link
Copy Markdown
Contributor Author

Resolved the conflict with #291 by merging master in; the new tests sit next to the CDATA and declaration tests, and the full suite passes.

@frostming
frostming merged commit f1ff225 into frostming:master Nov 9, 2026
1 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants