Skip to content

Commit 369fac2

Browse files
committed
Merge remote-tracking branch 'origin/fix-GHSL-2022-109'
2 parents 932cfce + b4f0106 commit 369fac2

File tree

5 files changed

+29
-3
lines changed

5 files changed

+29
-3
lines changed

src/blocks.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <stdlib.h>
99
#include <assert.h>
1010
#include <stdio.h>
11+
#include <limits.h>
1112

1213
#include "cmark_ctype.h"
1314
#include "syntax_extension.h"
@@ -639,6 +640,14 @@ static cmark_node *finalize_document(cmark_parser *parser) {
639640
}
640641

641642
finalize(parser, parser->root);
643+
644+
// Limit total size of extra content created from reference links to
645+
// document size to avoid superlinear growth. Always allow 100KB.
646+
if (parser->total_size > 100000)
647+
parser->refmap->max_ref_size = parser->total_size;
648+
else
649+
parser->refmap->max_ref_size = 100000;
650+
642651
process_inlines(parser, parser->refmap, parser->options);
643652
if (parser->options & CMARK_OPT_FOOTNOTES)
644653
process_footnotes(parser);
@@ -698,6 +707,11 @@ static void S_parser_feed(cmark_parser *parser, const unsigned char *buffer,
698707
const unsigned char *end = buffer + len;
699708
static const uint8_t repl[] = {239, 191, 189};
700709

710+
if (len > UINT_MAX - parser->total_size)
711+
parser->total_size = UINT_MAX;
712+
else
713+
parser->total_size += len;
714+
701715
if (parser->last_buffer_ended_with_cr && *buffer == '\n') {
702716
// skip NL if last buffer ended with CR ; see #117
703717
buffer++;

src/map.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static void sort_map(cmark_map *map) {
7373

7474
cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label) {
7575
cmark_map_entry **ref = NULL;
76+
cmark_map_entry *r = NULL;
7677
unsigned char *norm;
7778

7879
if (label->len < 1 || label->len > MAX_LINK_LABEL_LENGTH)
@@ -91,10 +92,15 @@ cmark_map_entry *cmark_map_lookup(cmark_map *map, cmark_chunk *label) {
9192
ref = (cmark_map_entry **)bsearch(norm, map->sorted, map->size, sizeof(cmark_map_entry *), refsearch);
9293
map->mem->free(norm);
9394

94-
if (!ref)
95-
return NULL;
95+
if (ref != NULL) {
96+
r = ref[0];
97+
/* Check for expansion limit */
98+
if (r->size > map->max_ref_size - map->ref_size)
99+
return NULL;
100+
map->ref_size += r->size;
101+
}
96102

97-
return ref[0];
103+
return r;
98104
}
99105

100106
void cmark_map_free(cmark_map *map) {
@@ -118,5 +124,6 @@ cmark_map *cmark_map_new(cmark_mem *mem, cmark_map_free_f free) {
118124
cmark_map *map = (cmark_map *)mem->calloc(1, sizeof(cmark_map));
119125
map->mem = mem;
120126
map->free = free;
127+
map->max_ref_size = UINT_MAX;
121128
return map;
122129
}

src/map.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ struct cmark_map_entry {
1111
struct cmark_map_entry *next;
1212
unsigned char *label;
1313
unsigned int age;
14+
unsigned int size;
1415
};
1516

1617
typedef struct cmark_map_entry cmark_map_entry;
@@ -24,6 +25,8 @@ struct cmark_map {
2425
cmark_map_entry *refs;
2526
cmark_map_entry **sorted;
2627
unsigned int size;
28+
unsigned int ref_size;
29+
unsigned int max_ref_size;
2730
cmark_map_free_f free;
2831
};
2932

src/parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct cmark_parser {
4646
/* Options set by the user, see the Options section in cmark.h */
4747
int options;
4848
bool last_buffer_ended_with_cr;
49+
unsigned int total_size;
4950
cmark_llist *syntax_extensions;
5051
cmark_llist *inline_syntax_extensions;
5152
cmark_ispunct_func backslash_ispunct;

src/references.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ void cmark_reference_create(cmark_map *map, cmark_chunk *label,
3232
ref->title = cmark_clean_title(map->mem, title);
3333
ref->entry.age = map->size;
3434
ref->entry.next = map->refs;
35+
ref->entry.size = ref->url.len + ref->title.len;
3536

3637
map->refs = (cmark_map_entry *)ref;
3738
map->size++;

0 commit comments

Comments
 (0)