From a9da6782761e4d3ac7dfd3193fa43b73824afef4 Mon Sep 17 00:00:00 2001 From: Yuki Izumi Date: Thu, 1 Dec 2016 20:52:42 +1100 Subject: Allow balanced nested parens in link destinations (#166) --- src/inlines.c | 87 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 25 deletions(-) (limited to 'src/inlines.c') diff --git a/src/inlines.c b/src/inlines.c index f1c863f..c9cccfe 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -823,7 +823,44 @@ noMatch: subj->pos = startpos; // rewind return 0; } +static bufsize_t manual_scan_link_url(cmark_chunk *input, bufsize_t offset) { + bufsize_t i = offset; + size_t nb_p = 0; + + if (i < input->len && input->data[i] == '<') { + ++i; + while (i < input->len) { + if (input->data[i] == '>') { + ++i; + break; + } else if (input->data[i] == '\\') + i += 2; + else if (cmark_isspace(input->data[i])) + return -1; + else + ++i; + } + } else { + while (i < input->len) { + if (input->data[i] == '\\') + i += 2; + else if (input->data[i] == '(') { + ++nb_p; ++i; + } else if (input->data[i] == ')') { + if (nb_p == 0) + break; + --nb_p; ++i; + } else if (cmark_isspace(input->data[i])) + break; + else + ++i; + } + } + if (i >= input->len) + return -1; + return i - offset; +} // Return a link, an image, or a literal close bracket. static cmark_node *handle_close_bracket(subject *subj) { bufsize_t initial_pos, after_link_text_pos; @@ -865,7 +902,7 @@ static cmark_node *handle_close_bracket(subject *subj) { // First, look for an inline link. if (peek_char(subj) == '(' && ((sps = scan_spacechars(&subj->input, subj->pos + 1)) > -1) && - ((n = scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) { + ((n = manual_scan_link_url(&subj->input, subj->pos + 1 + sps)) > -1)) { // try to parse an explicit link: starturl = subj->pos + 1 + sps; // after ( @@ -996,31 +1033,31 @@ static cmark_node *handle_newline(subject *subj) { static bufsize_t subject_find_special_char(subject *subj, int options) { // "\r\n\\`&_*[]pos + 1; @@ -1171,8 +1208,8 @@ bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_strbuf *input, // parse link url: spnl(&subj); - matchlen = scan_link_url(&subj.input, subj.pos); - if (matchlen) { + matchlen = manual_scan_link_url(&subj.input, subj.pos); + if (matchlen > 0) { url = cmark_chunk_dup(&subj.input, subj.pos, matchlen); subj.pos += matchlen; } else { -- cgit v1.2.3