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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e13ce6bba89ae75cedfa740776ebacf43cc4c304f576aff0d5d795c5b9264e83
4
- data.tar.gz: '03805285731cd7a7ddf1b856f572a3625c513d346f3e6fce7805d49a75a8c975'
3
+ metadata.gz: 8197daf1b6113b658c30459c0c4436ee688bfdd2381d3f541ff31bf3c3177bae
4
+ data.tar.gz: 25761b81607e28e9f569a61f502913c55f88319023b7d12e362d87dd37a935f7
5
5
  SHA512:
6
- metadata.gz: daffcc63f38700d806bbc9fa586fdb27855aec89b9fa7a6277accccabff40cb0adfd9e469eec2d992a540b038b5348e2b275b25d191cd1ee4ce38ccdc9a2094a
7
- data.tar.gz: bef345d402340ace137b25ba5c0c78255252d347f5f637cfb3dff4c0407b554da958a7a9c14893dee523fd203c4b0ce5f2a5a696cdf83051eb5985aa4e116bab
6
+ metadata.gz: 822690178eaaedc1e173e81e1d7c302d1670b95d362ca056ac9552df81a46861f582e4624698325e7d9bac347079fb4af6f99d88fbd832d40b84c4cbaff16cfc
7
+ data.tar.gz: 19150ccc6ec605f469e09fcf56a4dcb40f5b6e1125ca890bad8a2e6dc8931abcf82c533535222340c6377b16f243dd95717b7158bf2836118b8e1542802a6afe
@@ -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)) {
@@ -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) &&
@@ -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:
@@ -105,6 +105,7 @@ struct cmark_node {
105
105
  cmark_link link;
106
106
  cmark_custom custom;
107
107
  int html_block_type;
108
+ int cell_index; // For keeping track of TABLE_CELL table alignments
108
109
  void *opaque;
109
110
  } as;
110
111
  };
@@ -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 *marker_row = NULL;
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 marker row.
274
- marker_row = row_from_string(self, parser,
275
- input + cmark_parser_get_first_nonspace(parser),
276
- len - cmark_parser_get_first_nonspace(parser));
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 (!marker_row) {
327
+ if (!delimiter_row) {
279
328
  return parent_container;
280
329
  }
281
-
282
- assert(marker_row);
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 != marker_row->n_columns) {
293
- free_table_row(parser->mem, marker_row);
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
- marker_row = row_from_string(
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 (!marker_row || !header_row || header_row->n_columns != marker_row->n_columns) {
308
- free_table_row(parser->mem, marker_row);
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, marker_row);
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 marker_row->n_columns
330
- // since we populate the alignments array based on marker_row->cells
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(marker_row->n_columns, sizeof(uint8_t));
333
- for (i = 0; i < marker_row->n_columns; ++i) {
334
- node_cell *node = &marker_row->cells[i];
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
- for (i = 0; i < header_row->n_columns; ++i) {
358
- node_cell *cell = &header_row->cells[i];
359
- cmark_node *header_cell = cmark_parser_add_child(parser, table_header,
360
- CMARK_NODE_TABLE_CELL, parent_container->start_column + cell->start_offset);
361
- header_cell->start_line = header_cell->end_line = parent_container->start_line;
362
- header_cell->internal_offset = cell->internal_offset;
363
- header_cell->end_column = parent_container->start_column + cell->end_offset;
364
- cmark_node_set_string_content(header_cell, (char *) cell->buf->ptr);
365
- cmark_node_set_syntax_extension(header_cell, self);
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, marker_row);
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
- uint8_t *alignments = get_table_alignments(node->parent->parent);
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
- int i = 0;
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;
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CommonMarker
4
- VERSION = "0.23.9"
4
+ VERSION = "0.23.10"
5
5
  end
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.9
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-04-11 00:00:00.000000000 Z
12
+ date: 2023-07-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: awesome_print