Skip to content

Commit

Permalink
Fix table cannot be recoginsed without empty line (commonmark#154)
Browse files Browse the repository at this point in the history
* fix(table): recoginse-without-empty-line (commonmark#141)

* fix(table): fix bufsize_t not convert to uint16_t

* fix(table): fix uint16_6 not convert to int

* fix(table): fix uint16_6 not convert to int

* fix(table): clear unused type conversion

* restore whitespace

* Always free `paragraph_content`

`cmark_node_set_string_content` allocates and copies the data in
`paragraph_content` so it is not needed afterwards.

```
=================================================================
==14==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 24 byte(s) in 1 object(s) allocated from:
    0 0x4dd330 in calloc /src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:97
    1 0x59e243 in xcalloc /src/octofuzz/src/cmark.c:18:15
    2 0x58fd75 in unescape_pipes /src/octofuzz/extensions/table.c:95:39
    3 0x58fd75 in try_inserting_table_header_paragraph /src/octofuzz/extensions/table.c:187
    4 0x58fd75 in try_opening_table_header /src/octofuzz/extensions/table.c:254
    5 0x58fd75 in try_opening_table_block /src/octofuzz/extensions/table.c:370
    6 0x5b22d5 in open_new_blocks /src/octofuzz/src/blocks.c:1275:27
    7 0x5b22d5 in S_process_line /src/octofuzz/src/blocks.c:1465
    8 0x5aa7f0 in cmark_parser_finish /src/octofuzz/src/blocks.c:1492:5
    9 0x58f2fc in LLVMFuzzerTestOneInput /src/octofuzz/test/cmark-fuzz.c:46:23

Indirect leak of 8 byte(s) in 1 object(s) allocated from:
    0 0x4dd580 in realloc /src/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:107
    1 0x59e2d3 in xrealloc /src/octofuzz/src/cmark.c:27:19
    2 0x640364 in cmark_strbuf_grow /src/octofuzz/src/buffer.c:57:31
    3 0x640364 in cmark_strbuf_init /src/octofuzz/src/buffer.c:31
    4 0x58fd8b in unescape_pipes /src/octofuzz/extensions/table.c:98:3
    5 0x58fd8b in try_inserting_table_header_paragraph /src/octofuzz/extensions/table.c:187
    6 0x58fd8b in try_opening_table_header /src/octofuzz/extensions/table.c:254
    7 0x58fd8b in try_opening_table_block /src/octofuzz/extensions/table.c:370
    8 0x5b22d5 in open_new_blocks /src/octofuzz/src/blocks.c:1275:27
    9 0x5b22d5 in S_process_line /src/octofuzz/src/blocks.c:1465
    10 0x5aa7f0 in cmark_parser_finish /src/octofuzz/src/blocks.c:1492:5
    11 0x58f2fc in LLVMFuzzerTestOneInput /src/octofuzz/test/cmark-fuzz.c:46:23

SUMMARY: AddressSanitizer: 32 byte(s) leaked in 2 allocation(s).
```
  • Loading branch information
jinhucheung authored and Ashe Connor committed May 8, 2019
1 parent 10730e1 commit ef13dc5
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ bstrlib.txt
build
cmark.dSYM/*
cmark
.vscode

# Testing and benchmark
alltests.md
Expand Down
65 changes: 52 additions & 13 deletions extensions/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,

typedef struct {
uint16_t n_columns;
int paragraph_offset;
cmark_llist *cells;
} table_row;

Expand Down Expand Up @@ -115,6 +116,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
int len) {
table_row *row = NULL;
bufsize_t cell_matched = 1, pipe_matched = 1, offset;
int cell_end_offset;

row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
row->n_columns = 0;
Expand All @@ -129,20 +131,32 @@ static table_row *row_from_string(cmark_syntax_extension *self,
pipe_matched = scan_table_cell_end(string, len, offset + cell_matched);

if (cell_matched || pipe_matched) {
cmark_strbuf *cell_buf = unescape_pipes(parser->mem, string + offset,
cell_matched);
cmark_strbuf_trim(cell_buf);

node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
cell->buf = cell_buf;
cell->start_offset = offset;
cell->end_offset = offset + cell_matched - 1;
while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
--cell->start_offset;
++cell->internal_offset;
cell_end_offset = offset + cell_matched - 1;

if (string[cell_end_offset] == '\n' || string[cell_end_offset] == '\r') {
row->paragraph_offset = cell_end_offset;

cmark_llist_free_full(parser->mem, row->cells, (cmark_free_func)free_table_cell);
row->cells = NULL;
row->n_columns = 0;
} else {
cmark_strbuf *cell_buf = unescape_pipes(parser->mem, string + offset,
cell_matched);
cmark_strbuf_trim(cell_buf);

node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
cell->buf = cell_buf;
cell->start_offset = offset;
cell->end_offset = cell_end_offset;

while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
--cell->start_offset;
++cell->internal_offset;
}

row->n_columns += 1;
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
}
row->n_columns += 1;
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
}

offset += cell_matched + pipe_matched;
Expand All @@ -161,6 +175,26 @@ static table_row *row_from_string(cmark_syntax_extension *self,
return row;
}

static void try_inserting_table_header_paragraph(cmark_parser *parser,
cmark_node *parent_container,
unsigned char *parent_string,
int paragraph_offset) {
cmark_node *paragraph;
cmark_strbuf *paragraph_content;

paragraph = cmark_node_new_with_mem(CMARK_NODE_PARAGRAPH, parser->mem);

paragraph_content = unescape_pipes(parser->mem, parent_string, paragraph_offset);
cmark_strbuf_trim(paragraph_content);
cmark_node_set_string_content(paragraph, (char *) paragraph_content->ptr);
cmark_strbuf_free(paragraph_content);
parser->mem->free(paragraph_content);

if (!cmark_node_insert_before(parent_container, paragraph)) {
parser->mem->free(paragraph);
}
}

static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
cmark_parser *parser,
cmark_node *parent_container,
Expand Down Expand Up @@ -217,6 +251,11 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
return parent_container;
}

if (header_row->paragraph_offset) {
try_inserting_table_header_paragraph(parser, parent_container, (unsigned char *)parent_string,
header_row->paragraph_offset);
}

cmark_node_set_syntax_extension(parent_container, self);

parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
Expand Down
26 changes: 26 additions & 0 deletions test/extensions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,32 @@ Here's a link to [Freedom Planet 2][].
</table>
````````````````````````````````

### a table can be recognised when separated from a paragraph of text without an empty line

```````````````````````````````` example
123
456
| a | b |
| ---| --- |
d | e
.
<p>123
456</p>
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<tbody>
<tr>
<td>d</td>
<td>e</td>
</tr>
</tbody>
</table>
````````````````````````````````

## Strikethroughs

Expand Down

0 comments on commit ef13dc5

Please sign in to comment.