Skip to content

Commit 33a3c4d

Browse files
authored
Blocks: handle zero-length chunks in cmark_parser_feed (#635)
1 parent 067e1fd commit 33a3c4d

2 files changed

Lines changed: 22 additions & 0 deletions

File tree

‎api_test/main.c‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,22 @@ static void test_feed_across_line_ending(test_batch_runner *runner) {
954954
cmark_node_free(document);
955955
}
956956

957+
static void test_feed_empty_chunk(test_batch_runner *runner) {
958+
// An empty chunk between the CR and the LF must not split the line.
959+
// The chunk is exactly sized so that reading past its end trips ASan.
960+
cmark_parser *parser = cmark_parser_new(CMARK_OPT_DEFAULT);
961+
char *chunk = (char *)malloc(6);
962+
memcpy(chunk, "line1\r", 6);
963+
cmark_parser_feed(parser, chunk, 6);
964+
cmark_parser_feed(parser, chunk + 6, 0);
965+
free(chunk);
966+
cmark_parser_feed(parser, "\nline2\r\n", 8);
967+
cmark_node *document = cmark_parser_finish(parser);
968+
OK(runner, document->first_child->next == NULL, "document has one paragraph");
969+
cmark_parser_free(parser);
970+
cmark_node_free(document);
971+
}
972+
957973
static void sub_document(test_batch_runner *runner) {
958974
cmark_node *doc = cmark_node_new(CMARK_NODE_DOCUMENT);
959975
cmark_node *list = cmark_node_new(CMARK_NODE_LIST);
@@ -1206,6 +1222,7 @@ int main(void) {
12061222
test_cplusplus(runner);
12071223
test_safe(runner);
12081224
test_feed_across_line_ending(runner);
1225+
test_feed_empty_chunk(runner);
12091226
sub_document(runner);
12101227
source_pos(runner);
12111228
source_pos_inlines(runner);

‎src/blocks.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,11 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
578578
const unsigned char *end = buffer + len;
579579
static const uint8_t repl[] = {239, 191, 189};
580580

581+
// An empty chunk has nothing to process. Returning here also preserves
582+
// last_buffer_ended_with_cr and avoids reading past the end of buffer.
583+
if (len == 0)
584+
return;
585+
581586
if (len > UINT_MAX - parser->total_size)
582587
parser->total_size = UINT_MAX;
583588
else

0 commit comments

Comments
 (0)