Skip to content

Commit

Permalink
Merge pull request #47 from apple/QuietMisdreaus/upstream-update
Browse files Browse the repository at this point in the history
Update cmark-gfm base to 0.29.0.gfm.6
  • Loading branch information
QuietMisdreavus authored Oct 3, 2022
2 parents eb9a6a3 + c2479d6 commit bfdc057
Show file tree
Hide file tree
Showing 9 changed files with 2,563 additions and 2,470 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(cmark-gfm)
set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 29)
set(PROJECT_VERSION_PATCH 0)
set(PROJECT_VERSION_GFM 3)
set(PROJECT_VERSION_GFM 6)
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM})

include("FindAsan.cmake")
Expand Down
9 changes: 9 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
[0.29.0.gfm.6]
* Fixed polynomial time complexity DoS vulnerability in autolink extension

[0.29.0.gfm.5]
* Added xmpp: and mailto: support to the autolink extension

[0.29.0.gfm.4]
* Remove `source` from list of HTML blocks

[0.29.0.gfm.3]
* Fixed heap memory corruption vulnerabiliy via integer overflow per https://github.com/github/cmark-gfm/security/advisories/GHSA-mc3g-88wq-6f4x

Expand Down
37 changes: 34 additions & 3 deletions extensions/autolink.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,22 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
// inline was finished in inlines.c.
}

static bool validate_protocol(char protocol[], uint8_t *data, int rewind) {
size_t len = strlen(protocol);

// Check that the protocol matches
for (int i = 1; i <= len; i++) {
if (data[-rewind - i] != protocol[len - i]) {
return false;
}
}

char prev_char = data[-rewind - len - 1];

// Make sure the character before the protocol is non-alphanumeric
return !cmark_isalnum(prev_char);
}

static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset, int depth) {
// postprocess_text can recurse very deeply if there is a very long line of
// '@' only. Stop at a reasonable depth to ensure it cannot crash.
Expand All @@ -278,6 +294,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
uint8_t *data = text->as.literal.data,
*at;
size_t size = text->as.literal.len;
bool auto_mailto = true;
bool is_xmpp = false;
int rewind, max_rewind,
nb = 0, np = 0, ns = 0;

Expand All @@ -304,8 +322,18 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
if (strchr(".+-_", c) != NULL)
continue;

if (c == '/')
ns++;
if (strchr(":", c) != NULL) {
if (validate_protocol("mailto:", data, rewind)) {
auto_mailto = false;
continue;
}

if (validate_protocol("xmpp:", data, rewind)) {
auto_mailto = false;
is_xmpp = true;
continue;
}
}

break;
}
Expand All @@ -325,6 +353,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
nb++;
else if (c == '.' && link_end < size - 1 && cmark_isalnum(data[link_end + 1]))
np++;
else if (c == '/' && is_xmpp)
continue;
else if (c != '-' && c != '_')
break;
}
Expand All @@ -347,7 +377,8 @@ static void postprocess_text(cmark_parser *parser, cmark_node *text, int offset,
cmark_node *link_node = cmark_node_new_with_mem(CMARK_NODE_LINK, parser->mem);
cmark_strbuf buf;
cmark_strbuf_init(parser->mem, &buf, 10);
cmark_strbuf_puts(&buf, "mailto:");
if (auto_mailto)
cmark_strbuf_puts(&buf, "mailto:");
cmark_strbuf_put(&buf, data - rewind, (bufsize_t)(link_end + rewind));
link_node->as.link.url = cmark_chunk_buf_detach(&buf);

Expand Down
39 changes: 27 additions & 12 deletions src/inlines.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typedef struct bracket {
bracket_type type;
bool active;
bool bracket_after;
bool in_bracket[4];
} bracket;

typedef struct subject{
Expand Down Expand Up @@ -532,6 +533,7 @@ static void push_bracket(subject *subj, bracket_type type, cmark_node *inl_text)
bracket *b = (bracket *)subj->mem->calloc(1, sizeof(bracket));
if (subj->last_bracket != NULL) {
subj->last_bracket->bracket_after = true;
memcpy(b->in_bracket, subj->last_bracket->in_bracket, sizeof(b->in_bracket));
}
b->type = type;
b->active = true;
Expand All @@ -540,6 +542,7 @@ static void push_bracket(subject *subj, bracket_type type, cmark_node *inl_text)
b->previous_delimiter = subj->last_delim;
b->position = subj->pos;
b->bracket_after = false;
b->in_bracket[type] = true;
subj->last_bracket = b;
}

Expand Down Expand Up @@ -1401,6 +1404,17 @@ static cmark_node *handle_close_bracket(cmark_parser *parser, subject *subj) {
}
opener = opener->previous;
}
bool in_image = false;
if (opener) {
in_image = opener->in_bracket[IMAGE];
}
bracket *opener2 = subj->last_bracket;
while (opener2 != opener) {
if (opener2->type == IMAGE) {
opener2->in_bracket[IMAGE] = in_image;
}
opener2 = opener2->previous;
}
}

return NULL;
Expand Down Expand Up @@ -1891,19 +1905,20 @@ cmark_chunk *cmark_inline_parser_get_chunk(cmark_inline_parser *parser) {
}

int cmark_inline_parser_in_bracket(cmark_inline_parser *parser, int type) {
for (bracket *b = parser->last_bracket; b; b = b->previous) {
if (b->active) {
switch (type) {
case 0:
return b->type == LINK;
case 1:
return b->type == IMAGE;
case 2:
return b->type == ATTRIBUTE;
}
}
bracket *b = parser->last_bracket;
if (!b) {
return 0;
}
switch (type) {
case 0:
return b->in_bracket[LINK];
case 1:
return b->in_bracket[IMAGE];
case 2:
return b->in_bracket[ATTRIBUTE];
default:
return 0;
}
return 0;
}

void cmark_node_unput(cmark_node *node, int n) {
Expand Down
Loading

0 comments on commit bfdc057

Please sign in to comment.