Skip to content

Commit 4c40013

Browse files
Merge remote-tracking branch 'github/master' into QuietMisdreavus/sync-upstream
2 parents b9c0b19 + cf7577d commit 4c40013

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ project(cmark-gfm)
44
set(PROJECT_VERSION_MAJOR 0)
55
set(PROJECT_VERSION_MINOR 29)
66
set(PROJECT_VERSION_PATCH 0)
7-
set(PROJECT_VERSION_GFM 2)
7+
set(PROJECT_VERSION_GFM 3)
88
set(PROJECT_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}.gfm.${PROJECT_VERSION_GFM})
99

1010
include("FindAsan.cmake")

changelog.txt

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[0.29.0.gfm.3]
2+
* Fixed heap memory corruption vulnerabiliy via integer overflow per https://github.com/github/cmark-gfm/security/advisories/GHSA-mc3g-88wq-6f4x
3+
14
[0.29.0.gfm.2]
25
* Fixed issues with footnote rendering when used with the autolinker (#121),
36
and when footnotes are adjacent (#139).

extensions/table.c

+28-2
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
129129
bufsize_t cell_matched = 1, pipe_matched = 1, offset;
130130
int expect_more_cells = 1;
131131
int row_end_offset = 0;
132+
int int_overflow_abort = 0;
132133

133134
row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
134135
row->n_columns = 0;
@@ -161,6 +162,12 @@ static table_row *row_from_string(cmark_syntax_extension *self,
161162
++cell->internal_offset;
162163
}
163164

165+
// make sure we never wrap row->n_columns
166+
// offset will != len and our exit will clean up as intended
167+
if (row->n_columns == UINT16_MAX) {
168+
int_overflow_abort = 1;
169+
break;
170+
}
164171
row->n_columns += 1;
165172
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
166173
}
@@ -194,7 +201,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
194201
}
195202
}
196203

197-
if (offset != len || row->n_columns == 0) {
204+
if (offset != len || row->n_columns == 0 || int_overflow_abort) {
198205
free_table_row(parser->mem, row);
199206
row = NULL;
200207
}
@@ -241,6 +248,11 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
241248
marker_row = row_from_string(self, parser,
242249
input + cmark_parser_get_first_nonspace(parser),
243250
len - cmark_parser_get_first_nonspace(parser));
251+
// assert may be optimized out, don't rely on it for security boundaries
252+
if (!marker_row) {
253+
return parent_container;
254+
}
255+
244256
assert(marker_row);
245257

246258
cmark_arena_push();
@@ -264,6 +276,12 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
264276
len - cmark_parser_get_first_nonspace(parser));
265277
header_row = row_from_string(self, parser, (unsigned char *)parent_string,
266278
(int)strlen(parent_string));
279+
// row_from_string can return NULL, add additional check to ensure n_columns match
280+
if (!marker_row || !header_row || header_row->n_columns != marker_row->n_columns) {
281+
free_table_row(parser->mem, marker_row);
282+
free_table_row(parser->mem, header_row);
283+
return parent_container;
284+
}
267285
}
268286

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

302+
// allocate alignments based on marker_row->n_columns
303+
// since we populate the alignments array based on marker_row->cells
284304
uint8_t *alignments =
285-
(uint8_t *)parser->mem->calloc(header_row->n_columns, sizeof(uint8_t));
305+
(uint8_t *)parser->mem->calloc(marker_row->n_columns, sizeof(uint8_t));
286306
cmark_llist *it = marker_row->cells;
287307
for (i = 0; it; it = it->next, ++i) {
288308
node_cell *node = (node_cell *)it->data;
@@ -351,6 +371,12 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
351371
row = row_from_string(self, parser, input + cmark_parser_get_first_nonspace(parser),
352372
len - cmark_parser_get_first_nonspace(parser));
353373

374+
if (!row) {
375+
// clean up the dangling node
376+
cmark_node_free(table_row_block);
377+
return NULL;
378+
}
379+
354380
{
355381
cmark_llist *tmp;
356382
int i, table_columns = get_n_table_columns(parent_container);

0 commit comments

Comments
 (0)