Skip to content

Commit ef13dc5

Browse files
jinhucheungAshe Connor
authored andcommitted
Fix table cannot be recoginsed without empty line (commonmark#154)
* 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). ```
1 parent 10730e1 commit ef13dc5

File tree

3 files changed

+79
-13
lines changed

3 files changed

+79
-13
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ bstrlib.txt
3232
build
3333
cmark.dSYM/*
3434
cmark
35+
.vscode
3536

3637
# Testing and benchmark
3738
alltests.md

extensions/table.c

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
1616

1717
typedef struct {
1818
uint16_t n_columns;
19+
int paragraph_offset;
1920
cmark_llist *cells;
2021
} table_row;
2122

@@ -115,6 +116,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
115116
int len) {
116117
table_row *row = NULL;
117118
bufsize_t cell_matched = 1, pipe_matched = 1, offset;
119+
int cell_end_offset;
118120

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

131133
if (cell_matched || pipe_matched) {
132-
cmark_strbuf *cell_buf = unescape_pipes(parser->mem, string + offset,
133-
cell_matched);
134-
cmark_strbuf_trim(cell_buf);
135-
136-
node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
137-
cell->buf = cell_buf;
138-
cell->start_offset = offset;
139-
cell->end_offset = offset + cell_matched - 1;
140-
while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
141-
--cell->start_offset;
142-
++cell->internal_offset;
134+
cell_end_offset = offset + cell_matched - 1;
135+
136+
if (string[cell_end_offset] == '\n' || string[cell_end_offset] == '\r') {
137+
row->paragraph_offset = cell_end_offset;
138+
139+
cmark_llist_free_full(parser->mem, row->cells, (cmark_free_func)free_table_cell);
140+
row->cells = NULL;
141+
row->n_columns = 0;
142+
} else {
143+
cmark_strbuf *cell_buf = unescape_pipes(parser->mem, string + offset,
144+
cell_matched);
145+
cmark_strbuf_trim(cell_buf);
146+
147+
node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
148+
cell->buf = cell_buf;
149+
cell->start_offset = offset;
150+
cell->end_offset = cell_end_offset;
151+
152+
while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
153+
--cell->start_offset;
154+
++cell->internal_offset;
155+
}
156+
157+
row->n_columns += 1;
158+
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
143159
}
144-
row->n_columns += 1;
145-
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
146160
}
147161

148162
offset += cell_matched + pipe_matched;
@@ -161,6 +175,26 @@ static table_row *row_from_string(cmark_syntax_extension *self,
161175
return row;
162176
}
163177

178+
static void try_inserting_table_header_paragraph(cmark_parser *parser,
179+
cmark_node *parent_container,
180+
unsigned char *parent_string,
181+
int paragraph_offset) {
182+
cmark_node *paragraph;
183+
cmark_strbuf *paragraph_content;
184+
185+
paragraph = cmark_node_new_with_mem(CMARK_NODE_PARAGRAPH, parser->mem);
186+
187+
paragraph_content = unescape_pipes(parser->mem, parent_string, paragraph_offset);
188+
cmark_strbuf_trim(paragraph_content);
189+
cmark_node_set_string_content(paragraph, (char *) paragraph_content->ptr);
190+
cmark_strbuf_free(paragraph_content);
191+
parser->mem->free(paragraph_content);
192+
193+
if (!cmark_node_insert_before(parent_container, paragraph)) {
194+
parser->mem->free(paragraph);
195+
}
196+
}
197+
164198
static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
165199
cmark_parser *parser,
166200
cmark_node *parent_container,
@@ -217,6 +251,11 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
217251
return parent_container;
218252
}
219253

254+
if (header_row->paragraph_offset) {
255+
try_inserting_table_header_paragraph(parser, parent_container, (unsigned char *)parent_string,
256+
header_row->paragraph_offset);
257+
}
258+
220259
cmark_node_set_syntax_extension(parent_container, self);
221260

222261
parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));

test/extensions.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,32 @@ Here's a link to [Freedom Planet 2][].
472472
</table>
473473
````````````````````````````````
474474

475+
### a table can be recognised when separated from a paragraph of text without an empty line
476+
477+
```````````````````````````````` example
478+
123
479+
456
480+
| a | b |
481+
| ---| --- |
482+
d | e
483+
.
484+
<p>123
485+
456</p>
486+
<table>
487+
<thead>
488+
<tr>
489+
<th>a</th>
490+
<th>b</th>
491+
</tr>
492+
</thead>
493+
<tbody>
494+
<tr>
495+
<td>d</td>
496+
<td>e</td>
497+
</tr>
498+
</tbody>
499+
</table>
500+
````````````````````````````````
475501

476502
## Strikethroughs
477503

0 commit comments

Comments
 (0)