Skip to content

Commit

Permalink
Merge pull request from GHSA-mc3g-88wq-6f4x
Browse files Browse the repository at this point in the history
0.29.0.gfm.3 patch
  • Loading branch information
phillmv authored Mar 3, 2022
2 parents 766f161 + ff164f1 commit cf7577d
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 3 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 2)
set(PROJECT_VERSION_GFM 3)
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM})

include("FindAsan.cmake")
Expand Down
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[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

[0.29.0.gfm.2]
* Fixed issues with footnote rendering when used with the autolinker (#121),
and when footnotes are adjacent (#139).
Expand Down
30 changes: 28 additions & 2 deletions extensions/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
bufsize_t cell_matched = 1, pipe_matched = 1, offset;
int expect_more_cells = 1;
int row_end_offset = 0;
int int_overflow_abort = 0;

row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
row->n_columns = 0;
Expand Down Expand Up @@ -161,6 +162,12 @@ static table_row *row_from_string(cmark_syntax_extension *self,
++cell->internal_offset;
}

// make sure we never wrap row->n_columns
// offset will != len and our exit will clean up as intended
if (row->n_columns == UINT16_MAX) {
int_overflow_abort = 1;
break;
}
row->n_columns += 1;
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
}
Expand Down Expand Up @@ -194,7 +201,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
}
}

if (offset != len || row->n_columns == 0) {
if (offset != len || row->n_columns == 0 || int_overflow_abort) {
free_table_row(parser->mem, row);
row = NULL;
}
Expand Down Expand Up @@ -241,6 +248,11 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
marker_row = row_from_string(self, parser,
input + cmark_parser_get_first_nonspace(parser),
len - cmark_parser_get_first_nonspace(parser));
// assert may be optimized out, don't rely on it for security boundaries
if (!marker_row) {
return parent_container;
}

assert(marker_row);

cmark_arena_push();
Expand All @@ -264,6 +276,12 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
len - cmark_parser_get_first_nonspace(parser));
header_row = row_from_string(self, parser, (unsigned char *)parent_string,
(int)strlen(parent_string));
// row_from_string can return NULL, add additional check to ensure n_columns match
if (!marker_row || !header_row || header_row->n_columns != marker_row->n_columns) {
free_table_row(parser->mem, marker_row);
free_table_row(parser->mem, header_row);
return parent_container;
}
}

if (!cmark_node_set_type(parent_container, CMARK_NODE_TABLE)) {
Expand All @@ -281,8 +299,10 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
set_n_table_columns(parent_container, header_row->n_columns);

// allocate alignments based on marker_row->n_columns
// since we populate the alignments array based on marker_row->cells
uint8_t *alignments =
(uint8_t *)parser->mem->calloc(header_row->n_columns, sizeof(uint8_t));
(uint8_t *)parser->mem->calloc(marker_row->n_columns, sizeof(uint8_t));
cmark_llist *it = marker_row->cells;
for (i = 0; it; it = it->next, ++i) {
node_cell *node = (node_cell *)it->data;
Expand Down Expand Up @@ -351,6 +371,12 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
row = row_from_string(self, parser, input + cmark_parser_get_first_nonspace(parser),
len - cmark_parser_get_first_nonspace(parser));

if (!row) {
// clean up the dangling node
cmark_node_free(table_row_block);
return NULL;
}

{
cmark_llist *tmp;
int i, table_columns = get_n_table_columns(parent_container);
Expand Down

0 comments on commit cf7577d

Please sign in to comment.