Commit d32aa2e076960fc8d9401dfb03d3802cf0f1390f

Martin Mitas 2019-02-09T10:40:52

Fix conflict in parsing permissive autolinks and ordinary links. The issues is caused by the fact that we do not know exact position of permissive auto-link in time of md_collect_marks() because there is no syntax to mark its end on the 1st place. This causes that eventually, the closer mark in ctx->marks[] can be out-of-order somewhat. As a consequence, if some other mark range (e.g. ordinary link) shadows the auto-link, the closer mark may be left outside the shadowed range and survive till the phase when we generate the output. We fix by using an extra mark flag to remember we did really output the opener mark, and output the closer only in such case. Fixes #53.

diff --git a/md4c/md4c.c b/md4c/md4c.c
index e7643cd..959acd9 100644
--- a/md4c/md4c.c
+++ b/md4c/md4c.c
@@ -2497,6 +2497,7 @@ struct MD_MARK_tag {
 #define MD_MARK_EMPH_MODULO3_2              (0x40 | 0x80)
 #define MD_MARK_EMPH_MODULO3_MASK           (0x40 | 0x80)
 #define MD_MARK_AUTOLINK                    0x20  /* Distinguisher for '<', '>'. */
+#define MD_MARK_VALIDPERMISSIVEAUTOLINK     0x20  /* For permissive autolinks. */
 
 
 static MD_MARK*
@@ -3988,11 +3989,20 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
                 case ':':       /* Permissive URL autolink. */
                 case '.':       /* Permissive WWW autolink. */
                 {
-                    const MD_MARK* opener = ((mark->flags & MD_MARK_OPENER) ? mark : &ctx->marks[mark->prev]);
-                    const MD_MARK* closer = &ctx->marks[opener->next];
+                    MD_MARK* opener = ((mark->flags & MD_MARK_OPENER) ? mark : &ctx->marks[mark->prev]);
+                    MD_MARK* closer = &ctx->marks[opener->next];
                     const CHAR* dest = STR(opener->end);
                     SZ dest_size = closer->beg - opener->end;
 
+                    /* For permissive auto-links we do not know closer mark
+                     * position at the time of md_collect_marks(), therefore
+                     * it can be out-of-order in ctx->marks[].
+                     *
+                     * With this flag, we make sure that we output the closer
+                     * only if we processed the opener. */
+                    if(mark->flags & MD_MARK_OPENER)
+                        closer->flags |= MD_MARK_VALIDPERMISSIVEAUTOLINK;
+
                     if(opener->ch == '@' || opener->ch == '.') {
                         dest_size += 7;
                         MD_TEMP_BUFFER(dest_size * sizeof(CHAR));
@@ -4003,8 +4013,9 @@ md_process_inlines(MD_CTX* ctx, const MD_LINE* lines, int n_lines)
                         dest = ctx->buffer;
                     }
 
-                    MD_CHECK(md_enter_leave_span_a(ctx, (mark->flags & MD_MARK_OPENER),
-                                MD_SPAN_A, dest, dest_size, TRUE, NULL, 0));
+                    if(closer->flags & MD_MARK_VALIDPERMISSIVEAUTOLINK)
+                        MD_CHECK(md_enter_leave_span_a(ctx, (mark->flags & MD_MARK_OPENER),
+                                    MD_SPAN_A, dest, dest_size, TRUE, NULL, 0));
                     break;
                 }
 
diff --git a/test/permissive-url-autolinks.txt b/test/permissive-url-autolinks.txt
index 000a86f..ebe1504 100644
--- a/test/permissive-url-autolinks.txt
+++ b/test/permissive-url-autolinks.txt
@@ -62,3 +62,18 @@ Anonymous FTP is available at ftp://foo.bar.baz.
 <p>(Visit <a href="https://encrypted.google.com/search?q=Markup+(business)">https://encrypted.google.com/search?q=Markup+(business)</a>)</p>
 <p>Anonymous FTP is available at <a href="ftp://foo.bar.baz">ftp://foo.bar.baz</a>.</p>
 ````````````````````````````````
+
+
+## GitHub Issues
+
+### [Issue 53](https://github.com/mity/md4c/issues/53)
+```````````````````````````````` example
+This is [link](http://github.com/).
+.
+<p>This is <a href="http://github.com/">link</a>.</p>
+````````````````````````````````
+```````````````````````````````` example
+This is [link](http://github.com/)X
+.
+<p>This is <a href="http://github.com/">link</a>X</p>
+````````````````````````````````
diff --git a/test/permissive-www-autolinks.txt b/test/permissive-www-autolinks.txt
index 245d260..71ccf93 100644
--- a/test/permissive-www-autolinks.txt
+++ b/test/permissive-www-autolinks.txt
@@ -90,3 +90,18 @@ www.commonmark.org/he<lp
 .
 <p><a href="http://www.commonmark.org/he">www.commonmark.org/he</a>&lt;lp</p>
 ````````````````````````````````
+
+
+## GitHub Issues
+
+### [Issue 53](https://github.com/mity/md4c/issues/53)
+```````````````````````````````` example
+This is [link](www.github.com/).
+.
+<p>This is <a href="www.github.com/">link</a>.</p>
+````````````````````````````````
+```````````````````````````````` example
+This is [link](www.github.com/)X
+.
+<p>This is <a href="www.github.com/">link</a>X</p>
+````````````````````````````````