@@ -70,22 +70,6 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
70
70
static void S_process_line (cmark_parser * parser , const unsigned char * buffer ,
71
71
bufsize_t bytes );
72
72
73
- static void subtract_open_block_counts (cmark_parser * parser , cmark_node * node ) {
74
- do {
75
- decr_open_block_count (parser , S_type (node ));
76
- node -> flags &= ~CMARK_NODE__OPEN_BLOCK ;
77
- node = node -> last_child ;
78
- } while (node );
79
- }
80
-
81
- static void add_open_block_counts (cmark_parser * parser , cmark_node * node ) {
82
- do {
83
- incr_open_block_count (parser , S_type (node ));
84
- node -> flags |= CMARK_NODE__OPEN_BLOCK ;
85
- node = node -> last_child ;
86
- } while (node );
87
- }
88
-
89
73
static cmark_node * make_block (cmark_mem * mem , cmark_node_type tag ,
90
74
int start_line , int start_column ) {
91
75
cmark_node * e ;
@@ -145,7 +129,6 @@ static void cmark_parser_reset(cmark_parser *parser) {
145
129
parser -> refmap = cmark_reference_map_new (parser -> mem );
146
130
parser -> root = document ;
147
131
parser -> current = document ;
148
- add_open_block_counts (parser , document );
149
132
150
133
parser -> syntax_extensions = saved_exts ;
151
134
parser -> inline_syntax_extensions = saved_inline_exts ;
@@ -259,18 +242,15 @@ static void remove_trailing_blank_lines(cmark_strbuf *ln) {
259
242
// Check to see if a node ends with a blank line, descending
260
243
// if needed into lists and sublists.
261
244
static bool S_ends_with_blank_line (cmark_node * node ) {
262
- while (true) {
263
- if (S_last_line_checked (node )) {
264
- return (S_last_line_blank (node ));
265
- } else if ((S_type (node ) == CMARK_NODE_LIST ||
266
- S_type (node ) == CMARK_NODE_ITEM ) && node -> last_child ) {
267
- S_set_last_line_checked (node );
268
- node = node -> last_child ;
269
- continue ;
270
- } else {
271
- S_set_last_line_checked (node );
272
- return (S_last_line_blank (node ));
273
- }
245
+ if (S_last_line_checked (node )) {
246
+ return (S_last_line_blank (node ));
247
+ } else if ((S_type (node ) == CMARK_NODE_LIST ||
248
+ S_type (node ) == CMARK_NODE_ITEM ) && node -> last_child ) {
249
+ S_set_last_line_checked (node );
250
+ return (S_ends_with_blank_line (node -> last_child ));
251
+ } else {
252
+ S_set_last_line_checked (node );
253
+ return (S_last_line_blank (node ));
274
254
}
275
255
}
276
256
@@ -330,12 +310,6 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
330
310
has_content = resolve_reference_link_definitions (parser , b );
331
311
if (!has_content ) {
332
312
// remove blank node (former reference def)
333
- if (b -> flags & CMARK_NODE__OPEN_BLOCK ) {
334
- decr_open_block_count (parser , S_type (b ));
335
- if (b -> prev ) {
336
- add_open_block_counts (parser , b -> prev );
337
- }
338
- }
339
313
cmark_node_free (b );
340
314
}
341
315
break ;
@@ -408,17 +382,6 @@ static cmark_node *finalize(cmark_parser *parser, cmark_node *b) {
408
382
return parent ;
409
383
}
410
384
411
- // Recalculates the number of open blocks. Returns true if it matches what's currently stored
412
- // in parser. (Used to check that the counts in parser, which are updated incrementally, are
413
- // correct.)
414
- bool check_open_block_counts (cmark_parser * parser ) {
415
- cmark_parser tmp_parser = {0 }; // Only used for its open_block_counts and total_open_blocks fields.
416
- add_open_block_counts (& tmp_parser , parser -> root );
417
- return
418
- tmp_parser .total_open_blocks == parser -> total_open_blocks &&
419
- memcmp (tmp_parser .open_block_counts , parser -> open_block_counts , sizeof (parser -> open_block_counts )) == 0 ;
420
- }
421
-
422
385
// Add a node as child of another. Return pointer to child.
423
386
static cmark_node * add_child (cmark_parser * parser , cmark_node * parent ,
424
387
cmark_node_type block_type , int start_column ) {
@@ -437,14 +400,11 @@ static cmark_node *add_child(cmark_parser *parser, cmark_node *parent,
437
400
if (parent -> last_child ) {
438
401
parent -> last_child -> next = child ;
439
402
child -> prev = parent -> last_child ;
440
- subtract_open_block_counts (parser , parent -> last_child );
441
403
} else {
442
404
parent -> first_child = child ;
443
405
child -> prev = NULL ;
444
406
}
445
407
parent -> last_child = child ;
446
- add_open_block_counts (parser , child );
447
-
448
408
return child ;
449
409
}
450
410
@@ -1087,14 +1047,8 @@ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
1087
1047
* all_matched = false;
1088
1048
cmark_node * container = parser -> root ;
1089
1049
cmark_node_type cont_type ;
1090
- cmark_parser tmp_parser ; // Only used for its open_block_counts and total_open_blocks fields.
1091
- memcpy (tmp_parser .open_block_counts , parser -> open_block_counts , sizeof (parser -> open_block_counts ));
1092
- tmp_parser .total_open_blocks = parser -> total_open_blocks ;
1093
-
1094
- assert (check_open_block_counts (parser ));
1095
1050
1096
1051
while (S_last_child_is_open (container )) {
1097
- decr_open_block_count (& tmp_parser , S_type (container ));
1098
1052
container = container -> last_child ;
1099
1053
cont_type = S_type (container );
1100
1054
@@ -1106,53 +1060,6 @@ static cmark_node *check_open_blocks(cmark_parser *parser, cmark_chunk *input,
1106
1060
continue ;
1107
1061
}
1108
1062
1109
- // This block of code is a workaround for the quadratic performance
1110
- // issue described here (issue 2):
1111
- //
1112
- // https://github.com/github/cmark-gfm/security/advisories/GHSA-66g8-4hjf-77xh
1113
- //
1114
- // If the current line is empty then we might be able to skip directly
1115
- // to the end of the list of open blocks. To determine whether this is
1116
- // possible, we have been maintaining a count of the number of
1117
- // different types of open blocks. The main criterium is that every
1118
- // remaining block, except the last element of the list, is a LIST or
1119
- // ITEM. The code below checks the conditions, and if they're ok, skips
1120
- // forward to parser->current.
1121
- if (parser -> blank && parser -> indent == 0 ) { // Current line is empty
1122
- // Make sure that parser->current doesn't point to a closed block.
1123
- if (parser -> current -> flags & CMARK_NODE__OPEN_BLOCK ) {
1124
- if (parser -> current -> flags & CMARK_NODE__OPEN ) {
1125
- const size_t n_list = read_open_block_count (& tmp_parser , CMARK_NODE_LIST );
1126
- const size_t n_item = read_open_block_count (& tmp_parser , CMARK_NODE_ITEM );
1127
- // At most one block can be something other than a LIST or ITEM.
1128
- if (n_list + n_item + 1 >= tmp_parser .total_open_blocks ) {
1129
- // Check that parser->current is suitable for jumping to.
1130
- switch (S_type (parser -> current )) {
1131
- case CMARK_NODE_LIST :
1132
- case CMARK_NODE_ITEM :
1133
- if (n_list + n_item != tmp_parser .total_open_blocks ) {
1134
- if (parser -> current -> last_child == NULL ) {
1135
- // There's another node type somewhere in the middle of
1136
- // the list, so don't attempt the optimization.
1137
- break ;
1138
- }
1139
- }
1140
- // fall through
1141
- case CMARK_NODE_CODE_BLOCK :
1142
- case CMARK_NODE_PARAGRAPH :
1143
- case CMARK_NODE_HTML_BLOCK :
1144
- // Jump to parser->current
1145
- container = parser -> current ;
1146
- cont_type = S_type (container );
1147
- break ;
1148
- default :
1149
- break ;
1150
- }
1151
- }
1152
- }
1153
- }
1154
- }
1155
-
1156
1063
switch (cont_type ) {
1157
1064
case CMARK_NODE_BLOCK_QUOTE :
1158
1065
if (!parse_block_quote_prefix (parser , input ))
@@ -1286,9 +1193,8 @@ static void open_new_blocks(cmark_parser *parser, cmark_node **container,
1286
1193
has_content = resolve_reference_link_definitions (parser , * container );
1287
1194
1288
1195
if (has_content ) {
1289
- cmark_node_set_type (* container , CMARK_NODE_HEADING );
1290
- decr_open_block_count (parser , CMARK_NODE_PARAGRAPH );
1291
- incr_open_block_count (parser , CMARK_NODE_HEADING );
1196
+
1197
+ (* container )-> type = (uint16_t )CMARK_NODE_HEADING ;
1292
1198
(* container )-> as .heading .level = lev ;
1293
1199
(* container )-> as .heading .setext = true;
1294
1200
S_advance_offset (parser , input , input -> len - 1 - parser -> offset , false);
@@ -1443,7 +1349,7 @@ static void add_text_to_container(cmark_parser *parser, cmark_node *container,
1443
1349
S_set_last_line_blank (container , last_line_blank );
1444
1350
1445
1351
tmp = container ;
1446
- while (tmp -> parent && S_last_line_blank ( tmp -> parent ) ) {
1352
+ while (tmp -> parent ) {
1447
1353
S_set_last_line_blank (tmp -> parent , false);
1448
1354
tmp = tmp -> parent ;
1449
1355
}
@@ -1572,7 +1478,6 @@ static void S_process_line(cmark_parser *parser, const unsigned char *buffer,
1572
1478
1573
1479
parser -> line_number ++ ;
1574
1480
1575
- assert (parser -> current -> next == NULL );
1576
1481
last_matched_container = check_open_blocks (parser , & input , & all_matched );
1577
1482
1578
1483
if (!last_matched_container )
0 commit comments