diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 4ef2a0543..0b4010a7b 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -70,6 +70,7 @@ Bug Fixes:: * Don't leave behind empty line inside skipped preprocessor conditional (#4580) * Don't duplicate block attribute line above detached block that breaks a dlist; fixes duplicate role on detached block (#4565) + * Don't crash when parsing xref shorthand if target starts with URL protocol and text is offset by space (#4570) == 2.0.22 (2024-03-08) - @mojavelinux diff --git a/lib/asciidoctor/rx.rb b/lib/asciidoctor/rx.rb index 5ba6ba1fd..1d7936645 100644 --- a/lib/asciidoctor/rx.rb +++ b/lib/asciidoctor/rx.rb @@ -522,9 +522,9 @@ module Rx; end # if RUBY_ENGINE == 'opal' # NOTE In JavaScript, a back reference succeeds if not set; invert the logic to give it a match to refute - InlineLinkRx = %r((^|link:|#{CG_BLANK}|\\?<(?=\\?(?:https?|file|ftp|irc)(:))|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|(?!\2)([^\s]*?)>|([^\s\[\]<]*([^\s,.?!\[\]<\)])))) + InlineLinkRx = %r((^|link:|#{CG_BLANK}|\\?<(?=\\?(?:https?|file|ftp|irc)(:))|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|(?!\2)([^\s]+?)>|([^\s\[\]<]*([^\s,.?!\[\]<\)])))) else - InlineLinkRx = %r((^|link:|#{CG_BLANK}|\\?<()|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|\2([^\s]*?)>|([^\s\[\]<]*([^\s,.?!\[\]<\)]))))m + InlineLinkRx = %r((^|link:|#{CG_BLANK}|\\?<()|[>\(\)\[\];"'])(\\?(?:https?|file|ftp|irc)://)(?:([^\s\[\]]+)\[(|#{CC_ALL}*?[^\\])\]|\2([^\s]+?)>|([^\s\[\]<]*([^\s,.?!\[\]<\)]))))m end # Match a link or e-mail inline macro. diff --git a/lib/asciidoctor/substitutors.rb b/lib/asciidoctor/substitutors.rb index 3f5bd6af6..e8c6325b5 100644 --- a/lib/asciidoctor/substitutors.rb +++ b/lib/asciidoctor/substitutors.rb @@ -538,9 +538,8 @@ def sub_macros text # honor the escapes next $&.slice 1, $&.length if $1.start_with? RS next %(#{$1}#{$&.slice $1.length + 1, $&.length}) if $3.start_with? RS - target = $3 + $6 - next $& if target == $3 - doc.register :links, target + next $& unless $6 + doc.register :links, (target = $3 + $6) link_text = (doc_attrs.key? 'hide-uri-scheme') ? (target.sub UriSniffRx, '') : target (Inline.new self, :anchor, link_text, type: :link, target: target, attributes: { 'role' => 'bare' }).convert else diff --git a/test/links_test.rb b/test/links_test.rb index 1c8fd4e4b..c78b1b9e9 100644 --- a/test/links_test.rb +++ b/test/links_test.rb @@ -105,6 +105,11 @@ assert_xpath '//p[text()=""]', convert_string('<\\http://asciidoc.org>'), 1 end + test 'xref shorthand with target that starts with URL protocol and has space after comma should not crash parser' do + output = convert_string_to_embedded '<>' + assert_include 'Example', output + end + test 'autolink containing text enclosed in angle brackets' do output = convert_string_to_embedded 'https://github.com//' assert_include 'https://github.com/<org>/', output