From cfcaa0068bf319974fdec283416fcee5035c2d70 Mon Sep 17 00:00:00 2001 From: Bas Alberts Date: Tue, 13 Sep 2022 12:05:53 -0400 Subject: [PATCH 1/3] Remove polynomial time complexity in autolink extension Cache the value computed by cmark_inline_parser_in_bracket so that it runs in O(1) time rather than O(n). This patch was contributed by @kevinbackhouse --- src/inlines.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/inlines.c b/src/inlines.c index 4a118a636..3cd3bc3d0 100644 --- a/src/inlines.c +++ b/src/inlines.c @@ -41,6 +41,8 @@ typedef struct bracket { bool image; bool active; bool bracket_after; + bool in_bracket_image0; + bool in_bracket_image1; } bracket; typedef struct subject{ @@ -516,6 +518,8 @@ static void push_bracket(subject *subj, bool image, cmark_node *inl_text) { bracket *b = (bracket *)subj->mem->calloc(1, sizeof(bracket)); if (subj->last_bracket != NULL) { subj->last_bracket->bracket_after = true; + b->in_bracket_image0 = subj->last_bracket->in_bracket_image0; + b->in_bracket_image1 = subj->last_bracket->in_bracket_image1; } b->image = image; b->active = true; @@ -524,6 +528,11 @@ static void push_bracket(subject *subj, bool image, cmark_node *inl_text) { b->previous_delimiter = subj->last_delim; b->position = subj->pos; b->bracket_after = false; + if (image) { + b->in_bracket_image1 = true; + } else { + b->in_bracket_image0 = true; + } subj->last_bracket = b; } @@ -1254,6 +1263,17 @@ static cmark_node *handle_close_bracket(cmark_parser *parser, subject *subj) { } opener = opener->previous; } + bool in_bracket_image1 = false; + if (opener) { + in_bracket_image1 = opener->in_bracket_image1; + } + bracket *opener2 = subj->last_bracket; + while (opener2 != opener) { + if (opener2->image) { + opener2->in_bracket_image1 = in_bracket_image1; + } + opener2 = opener2->previous; + } } return NULL; @@ -1662,10 +1682,15 @@ cmark_chunk *cmark_inline_parser_get_chunk(cmark_inline_parser *parser) { } int cmark_inline_parser_in_bracket(cmark_inline_parser *parser, int image) { - for (bracket *b = parser->last_bracket; b; b = b->previous) - if (b->active && b->image == (image != 0)) - return 1; - return 0; + bracket *b = parser->last_bracket; + if (!b) { + return 0; + } + if (image != 0) { + return b->in_bracket_image1; + } else { + return b->in_bracket_image0; + } } void cmark_node_unput(cmark_node *node, int n) { From 54b422d81a9377a45781270ca45b0f94117fcb2c Mon Sep 17 00:00:00 2001 From: Bas Alberts Date: Tue, 13 Sep 2022 13:25:31 -0400 Subject: [PATCH 2/3] Updated changelog for 0.29.0.gfm.6 --- changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.txt b/changelog.txt index 3ecf949bc..05cab2ac0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,6 @@ +[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 From d47a722d13a040ab095660ec8a814c6d0171c6b5 Mon Sep 17 00:00:00 2001 From: Bas Alberts Date: Tue, 13 Sep 2022 13:27:09 -0400 Subject: [PATCH 3/3] Bump version to `0.29.0.gfm.6` --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 42fefcee6..135932666 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 5) +set(PROJECT_VERSION_GFM 6) set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM}) include("FindAsan.cmake")