commonmarker 0.23.9 → 0.23.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/commonmarker/autolink.c +1 -1
- data/ext/commonmarker/blocks.c +4 -2
- data/ext/commonmarker/commonmark.c +1 -1
- data/ext/commonmarker/node.c +1 -0
- data/ext/commonmarker/node.h +1 -0
- data/ext/commonmarker/table.c +91 -46
- data/lib/commonmarker/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8197daf1b6113b658c30459c0c4436ee688bfdd2381d3f541ff31bf3c3177bae
|
4
|
+
data.tar.gz: 25761b81607e28e9f569a61f502913c55f88319023b7d12e362d87dd37a935f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 822690178eaaedc1e173e81e1d7c302d1670b95d362ca056ac9552df81a46861f582e4624698325e7d9bac347079fb4af6f99d88fbd832d40b84c4cbaff16cfc
|
7
|
+
data.tar.gz: 19150ccc6ec605f469e09fcf56a4dcb40f5b6e1125ca890bad8a2e6dc8931abcf82c533535222340c6377b16f243dd95717b7158bf2836118b8e1542802a6afe
|
data/ext/commonmarker/autolink.c
CHANGED
@@ -296,7 +296,7 @@ static cmark_node *match(cmark_syntax_extension *ext, cmark_parser *parser,
|
|
296
296
|
// inline was finished in inlines.c.
|
297
297
|
}
|
298
298
|
|
299
|
-
static bool validate_protocol(char protocol[], uint8_t *data, size_t rewind, size_t max_rewind) {
|
299
|
+
static bool validate_protocol(const char protocol[], uint8_t *data, size_t rewind, size_t max_rewind) {
|
300
300
|
size_t len = strlen(protocol);
|
301
301
|
|
302
302
|
if (len > (max_rewind - rewind)) {
|
data/ext/commonmarker/blocks.c
CHANGED
@@ -1217,15 +1217,17 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
|
|
1217
1217
|
parser->first_nonspace + 1);
|
1218
1218
|
S_advance_offset(parser, input, input->len - 1 - parser->offset, false);
|
1219
1219
|
} else if (!indented &&
|
1220
|
-
parser->options & CMARK_OPT_FOOTNOTES &&
|
1220
|
+
(parser->options & CMARK_OPT_FOOTNOTES) &&
|
1221
|
+
depth < MAX_LIST_DEPTH &&
|
1221
1222
|
(matched = scan_footnote_definition(input, parser->first_nonspace))) {
|
1222
1223
|
cmark_chunk c = cmark_chunk_dup(input, parser->first_nonspace + 2, matched - 2);
|
1223
|
-
cmark_chunk_to_cstr(parser->mem, &c);
|
1224
1224
|
|
1225
1225
|
while (c.data[c.len - 1] != ']')
|
1226
1226
|
--c.len;
|
1227
1227
|
--c.len;
|
1228
1228
|
|
1229
|
+
cmark_chunk_to_cstr(parser->mem, &c);
|
1230
|
+
|
1229
1231
|
S_advance_offset(parser, input, parser->first_nonspace + matched - parser->offset, false);
|
1230
1232
|
*container = add_child(parser, *container, CMARK_NODE_FOOTNOTE_DEFINITION, parser->first_nonspace + matched + 1);
|
1231
1233
|
(*container)->as.literal = c;
|
@@ -165,7 +165,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
165
165
|
char fencechar[2] = {'\0', '\0'};
|
166
166
|
size_t info_len, code_len;
|
167
167
|
char listmarker[LISTMARKER_SIZE];
|
168
|
-
char *emph_delim;
|
168
|
+
const char *emph_delim;
|
169
169
|
bool first_in_list_item;
|
170
170
|
bufsize_t marker_width;
|
171
171
|
bool allow_wrap = renderer->width > 0 && !(CMARK_OPT_NOBREAKS & options) &&
|
data/ext/commonmarker/node.c
CHANGED
@@ -377,6 +377,7 @@ const char *cmark_node_get_literal(cmark_node *node) {
|
|
377
377
|
case CMARK_NODE_HTML_INLINE:
|
378
378
|
case CMARK_NODE_CODE:
|
379
379
|
case CMARK_NODE_FOOTNOTE_REFERENCE:
|
380
|
+
case CMARK_NODE_FOOTNOTE_DEFINITION:
|
380
381
|
return cmark_chunk_to_cstr(NODE_MEM(node), &node->as.literal);
|
381
382
|
|
382
383
|
case CMARK_NODE_CODE_BLOCK:
|
data/ext/commonmarker/node.h
CHANGED
data/ext/commonmarker/table.c
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
#include "table.h"
|
12
12
|
#include "cmark-gfm-core-extensions.h"
|
13
13
|
|
14
|
+
// Limit to prevent a malicious input from causing a denial of service.
|
15
|
+
#define MAX_AUTOCOMPLETED_CELLS 0x80000
|
16
|
+
|
14
17
|
// Custom node flag, initialized in `create_table_extension`.
|
15
18
|
static cmark_node_internal_flags CMARK_NODE__TABLE_VISITED;
|
16
19
|
|
@@ -31,6 +34,8 @@ typedef struct {
|
|
31
34
|
typedef struct {
|
32
35
|
uint16_t n_columns;
|
33
36
|
uint8_t *alignments;
|
37
|
+
int n_rows;
|
38
|
+
int n_nonempty_cells;
|
34
39
|
} node_table;
|
35
40
|
|
36
41
|
typedef struct {
|
@@ -83,6 +88,33 @@ static int set_n_table_columns(cmark_node *node, uint16_t n_columns) {
|
|
83
88
|
return 1;
|
84
89
|
}
|
85
90
|
|
91
|
+
// Increment the number of rows in the table. Also update n_nonempty_cells,
|
92
|
+
// which keeps track of the number of cells which were parsed from the
|
93
|
+
// input file. (If one of the rows is too short, then the trailing cells
|
94
|
+
// are autocompleted. Autocompleted cells are not counted in n_nonempty_cells.)
|
95
|
+
// The purpose of this is to prevent a malicious input from generating a very
|
96
|
+
// large number of autocompleted cells, which could cause a denial of service
|
97
|
+
// vulnerability.
|
98
|
+
static int incr_table_row_count(cmark_node *node, int i) {
|
99
|
+
if (!node || node->type != CMARK_NODE_TABLE) {
|
100
|
+
return 0;
|
101
|
+
}
|
102
|
+
|
103
|
+
((node_table *)node->as.opaque)->n_rows++;
|
104
|
+
((node_table *)node->as.opaque)->n_nonempty_cells += i;
|
105
|
+
return 1;
|
106
|
+
}
|
107
|
+
|
108
|
+
// Calculate the number of autocompleted cells.
|
109
|
+
static int get_n_autocompleted_cells(cmark_node *node) {
|
110
|
+
if (!node || node->type != CMARK_NODE_TABLE) {
|
111
|
+
return 0;
|
112
|
+
}
|
113
|
+
|
114
|
+
const node_table *nt = (node_table *)node->as.opaque;
|
115
|
+
return (nt->n_columns * nt->n_rows) - nt->n_nonempty_cells;
|
116
|
+
}
|
117
|
+
|
86
118
|
static uint8_t *get_table_alignments(cmark_node *node) {
|
87
119
|
if (!node || node->type != CMARK_NODE_TABLE)
|
88
120
|
return 0;
|
@@ -98,6 +130,23 @@ static int set_table_alignments(cmark_node *node, uint8_t *alignments) {
|
|
98
130
|
return 1;
|
99
131
|
}
|
100
132
|
|
133
|
+
static uint8_t get_cell_alignment(cmark_node *node) {
|
134
|
+
if (!node || node->type != CMARK_NODE_TABLE_CELL)
|
135
|
+
return 0;
|
136
|
+
|
137
|
+
const uint8_t *alignments = get_table_alignments(node->parent->parent);
|
138
|
+
int i = node->as.cell_index;
|
139
|
+
return alignments[i];
|
140
|
+
}
|
141
|
+
|
142
|
+
static int set_cell_index(cmark_node *node, int i) {
|
143
|
+
if (!node || node->type != CMARK_NODE_TABLE_CELL)
|
144
|
+
return 0;
|
145
|
+
|
146
|
+
node->as.cell_index = i;
|
147
|
+
return 1;
|
148
|
+
}
|
149
|
+
|
101
150
|
static cmark_strbuf *unescape_pipes(cmark_mem *mem, unsigned char *string, bufsize_t len)
|
102
151
|
{
|
103
152
|
cmark_strbuf *res = (cmark_strbuf *)mem->calloc(1, sizeof(cmark_strbuf));
|
@@ -257,7 +306,7 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
257
306
|
unsigned char *input, int len) {
|
258
307
|
cmark_node *table_header;
|
259
308
|
table_row *header_row = NULL;
|
260
|
-
table_row *
|
309
|
+
table_row *delimiter_row = NULL;
|
261
310
|
node_table_row *ntr;
|
262
311
|
const char *parent_string;
|
263
312
|
uint16_t i;
|
@@ -270,16 +319,16 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
270
319
|
return parent_container;
|
271
320
|
}
|
272
321
|
|
273
|
-
// Since scan_table_start was successful, we must have a
|
274
|
-
|
275
|
-
|
276
|
-
|
322
|
+
// Since scan_table_start was successful, we must have a delimiter row.
|
323
|
+
delimiter_row = row_from_string(
|
324
|
+
self, parser, input + cmark_parser_get_first_nonspace(parser),
|
325
|
+
len - cmark_parser_get_first_nonspace(parser));
|
277
326
|
// assert may be optimized out, don't rely on it for security boundaries
|
278
|
-
if (!
|
327
|
+
if (!delimiter_row) {
|
279
328
|
return parent_container;
|
280
329
|
}
|
281
|
-
|
282
|
-
assert(
|
330
|
+
|
331
|
+
assert(delimiter_row);
|
283
332
|
|
284
333
|
cmark_arena_push();
|
285
334
|
|
@@ -289,8 +338,8 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
289
338
|
parent_string = cmark_node_get_string_content(parent_container);
|
290
339
|
header_row = row_from_string(self, parser, (unsigned char *)parent_string,
|
291
340
|
(int)strlen(parent_string));
|
292
|
-
if (!header_row || header_row->n_columns !=
|
293
|
-
free_table_row(parser->mem,
|
341
|
+
if (!header_row || header_row->n_columns != delimiter_row->n_columns) {
|
342
|
+
free_table_row(parser->mem, delimiter_row);
|
294
343
|
free_table_row(parser->mem, header_row);
|
295
344
|
cmark_arena_pop();
|
296
345
|
parent_container->flags |= CMARK_NODE__TABLE_VISITED;
|
@@ -298,14 +347,14 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
298
347
|
}
|
299
348
|
|
300
349
|
if (cmark_arena_pop()) {
|
301
|
-
|
350
|
+
delimiter_row = row_from_string(
|
302
351
|
self, parser, input + cmark_parser_get_first_nonspace(parser),
|
303
352
|
len - cmark_parser_get_first_nonspace(parser));
|
304
353
|
header_row = row_from_string(self, parser, (unsigned char *)parent_string,
|
305
354
|
(int)strlen(parent_string));
|
306
355
|
// row_from_string can return NULL, add additional check to ensure n_columns match
|
307
|
-
if (!
|
308
|
-
free_table_row(parser->mem,
|
356
|
+
if (!delimiter_row || !header_row || header_row->n_columns != delimiter_row->n_columns) {
|
357
|
+
free_table_row(parser->mem, delimiter_row);
|
309
358
|
free_table_row(parser->mem, header_row);
|
310
359
|
return parent_container;
|
311
360
|
}
|
@@ -313,7 +362,7 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
313
362
|
|
314
363
|
if (!cmark_node_set_type(parent_container, CMARK_NODE_TABLE)) {
|
315
364
|
free_table_row(parser->mem, header_row);
|
316
|
-
free_table_row(parser->mem,
|
365
|
+
free_table_row(parser->mem, delimiter_row);
|
317
366
|
return parent_container;
|
318
367
|
}
|
319
368
|
|
@@ -326,12 +375,12 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
326
375
|
parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
|
327
376
|
set_n_table_columns(parent_container, header_row->n_columns);
|
328
377
|
|
329
|
-
// allocate alignments based on
|
330
|
-
// since we populate the alignments array based on
|
378
|
+
// allocate alignments based on delimiter_row->n_columns
|
379
|
+
// since we populate the alignments array based on delimiter_row->cells
|
331
380
|
uint8_t *alignments =
|
332
|
-
(uint8_t *)parser->mem->calloc(
|
333
|
-
for (i = 0; i <
|
334
|
-
node_cell *node = &
|
381
|
+
(uint8_t *)parser->mem->calloc(delimiter_row->n_columns, sizeof(uint8_t));
|
382
|
+
for (i = 0; i < delimiter_row->n_columns; ++i) {
|
383
|
+
node_cell *node = &delimiter_row->cells[i];
|
335
384
|
bool left = node->buf->ptr[0] == ':', right = node->buf->ptr[node->buf->size - 1] == ':';
|
336
385
|
|
337
386
|
if (left && right)
|
@@ -353,25 +402,26 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
353
402
|
table_header->as.opaque = ntr = (node_table_row *)parser->mem->calloc(1, sizeof(node_table_row));
|
354
403
|
ntr->is_header = true;
|
355
404
|
|
356
|
-
{
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
}
|
405
|
+
for (i = 0; i < header_row->n_columns; ++i) {
|
406
|
+
node_cell *cell = &header_row->cells[i];
|
407
|
+
cmark_node *header_cell = cmark_parser_add_child(parser, table_header,
|
408
|
+
CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
|
409
|
+
header_cell->start_line = header_cell->end_line = parent_container->start_line;
|
410
|
+
header_cell->internal_offset = cell->internal_offset;
|
411
|
+
header_cell->end_column = parent_container->start_column + cell->end_offset;
|
412
|
+
cmark_node_set_string_content(header_cell, (char *) cell->buf->ptr);
|
413
|
+
cmark_node_set_syntax_extension(header_cell, self);
|
414
|
+
set_cell_index(header_cell, i);
|
367
415
|
}
|
368
416
|
|
417
|
+
incr_table_row_count(parent_container, i);
|
418
|
+
|
369
419
|
cmark_parser_advance_offset(
|
370
420
|
parser, (char *)input,
|
371
421
|
(int)strlen((char *)input) - 1 - cmark_parser_get_offset(parser), false);
|
372
422
|
|
373
423
|
free_table_row(parser->mem, header_row);
|
374
|
-
free_table_row(parser->mem,
|
424
|
+
free_table_row(parser->mem, delimiter_row);
|
375
425
|
return parent_container;
|
376
426
|
}
|
377
427
|
|
@@ -385,6 +435,10 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
|
|
385
435
|
if (cmark_parser_is_blank(parser))
|
386
436
|
return NULL;
|
387
437
|
|
438
|
+
if (get_n_autocompleted_cells(parent_container) > MAX_AUTOCOMPLETED_CELLS) {
|
439
|
+
return NULL;
|
440
|
+
}
|
441
|
+
|
388
442
|
table_row_block =
|
389
443
|
cmark_parser_add_child(parser, parent_container, CMARK_NODE_TABLE_ROW,
|
390
444
|
parent_container->start_column);
|
@@ -412,12 +466,16 @@ static cmark_node *try_opening_table_row(cmark_syntax_extension *self,
|
|
412
466
|
node->end_column = parent_container->start_column + cell->end_offset;
|
413
467
|
cmark_node_set_string_content(node, (char *) cell->buf->ptr);
|
414
468
|
cmark_node_set_syntax_extension(node, self);
|
469
|
+
set_cell_index(node, i);
|
415
470
|
}
|
416
471
|
|
472
|
+
incr_table_row_count(parent_container, i);
|
473
|
+
|
417
474
|
for (; i < table_columns; ++i) {
|
418
475
|
cmark_node *node = cmark_parser_add_child(
|
419
476
|
parser, table_row_block, CMARK_NODE_TABLE_CELL, 0);
|
420
477
|
cmark_node_set_syntax_extension(node, self);
|
478
|
+
set_cell_index(node, i);
|
421
479
|
}
|
422
480
|
}
|
423
481
|
|
@@ -602,13 +660,7 @@ static const char *xml_attr(cmark_syntax_extension *extension,
|
|
602
660
|
cmark_node *node) {
|
603
661
|
if (node->type == CMARK_NODE_TABLE_CELL) {
|
604
662
|
if (cmark_gfm_extensions_get_table_row_is_header(node->parent)) {
|
605
|
-
|
606
|
-
int i = 0;
|
607
|
-
cmark_node *n;
|
608
|
-
for (n = node->parent->first_child; n; n = n->next, ++i)
|
609
|
-
if (n == node)
|
610
|
-
break;
|
611
|
-
switch (alignments[i]) {
|
663
|
+
switch (get_cell_alignment(node)) {
|
612
664
|
case 'l': return " align=\"left\"";
|
613
665
|
case 'c': return " align=\"center\"";
|
614
666
|
case 'r': return " align=\"right\"";
|
@@ -696,7 +748,6 @@ static void html_render(cmark_syntax_extension *extension,
|
|
696
748
|
cmark_event_type ev_type, int options) {
|
697
749
|
bool entering = (ev_type == CMARK_EVENT_ENTER);
|
698
750
|
cmark_strbuf *html = renderer->html;
|
699
|
-
cmark_node *n;
|
700
751
|
|
701
752
|
// XXX: we just monopolise renderer->opaque.
|
702
753
|
struct html_table_state *table_state =
|
@@ -745,7 +796,6 @@ static void html_render(cmark_syntax_extension *extension,
|
|
745
796
|
}
|
746
797
|
}
|
747
798
|
} else if (node->type == CMARK_NODE_TABLE_CELL) {
|
748
|
-
uint8_t *alignments = get_table_alignments(node->parent->parent);
|
749
799
|
if (entering) {
|
750
800
|
cmark_html_render_cr(html);
|
751
801
|
if (table_state->in_table_header) {
|
@@ -754,12 +804,7 @@ static void html_render(cmark_syntax_extension *extension,
|
|
754
804
|
cmark_strbuf_puts(html, "<td");
|
755
805
|
}
|
756
806
|
|
757
|
-
|
758
|
-
for (n = node->parent->first_child; n; n = n->next, ++i)
|
759
|
-
if (n == node)
|
760
|
-
break;
|
761
|
-
|
762
|
-
switch (alignments[i]) {
|
807
|
+
switch (get_cell_alignment(node)) {
|
763
808
|
case 'l': html_table_add_align(html, "left", options); break;
|
764
809
|
case 'c': html_table_add_align(html, "center", options); break;
|
765
810
|
case 'r': html_table_add_align(html, "right", options); break;
|
data/lib/commonmarker/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: commonmarker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.23.
|
4
|
+
version: 0.23.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garen Torikian
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-07-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: awesome_print
|