Skip to content

Commit 70f97f3

Browse files
authored
Merge pull request from GHSA-xxmq-4vph-956w
refmap: port github/cmark-gfm@b4f01062
2 parents ce795b7 + 7ce375d commit 70f97f3

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

src/parser/inlines.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub struct Subject<'a: 'd, 'r, 'o, 'd, 'i, 'c: 'subj, 'subj> {
2525
pub input: &'i [u8],
2626
pub pos: usize,
2727
flags: Flags,
28-
pub refmap: &'r mut HashMap<Vec<u8>, Reference>,
28+
pub refmap: &'r mut RefMap,
2929
delimiter_arena: &'d Arena<Delimiter<'a, 'd>>,
3030
last_delimiter: Option<&'d Delimiter<'a, 'd>>,
3131
brackets: Vec<Bracket<'a>>,
@@ -50,6 +50,37 @@ struct Flags {
5050
skip_html_comment: bool,
5151
}
5252

53+
pub struct RefMap {
54+
pub map: HashMap<Vec<u8>, Reference>,
55+
pub(crate) max_ref_size: usize,
56+
ref_size: usize,
57+
}
58+
59+
impl RefMap {
60+
pub fn new() -> Self {
61+
Self {
62+
map: HashMap::new(),
63+
max_ref_size: usize::MAX,
64+
ref_size: 0,
65+
}
66+
}
67+
68+
fn lookup(&mut self, lab: &[u8]) -> Option<Reference> {
69+
match self.map.get(lab) {
70+
Some(entry) => {
71+
let size = entry.url.len() + entry.title.len();
72+
if size > self.max_ref_size - self.ref_size {
73+
None
74+
} else {
75+
self.ref_size += size;
76+
Some(entry.clone())
77+
}
78+
}
79+
None => None,
80+
}
81+
}
82+
}
83+
5384
pub struct Delimiter<'a: 'd, 'd> {
5485
inl: &'a AstNode<'a>,
5586
position: usize,
@@ -73,7 +104,7 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
73104
arena: &'a Arena<AstNode<'a>>,
74105
options: &'o ComrakOptions,
75106
input: &'i [u8],
76-
refmap: &'r mut HashMap<Vec<u8>, Reference>,
107+
refmap: &'r mut RefMap,
77108
delimiter_arena: &'d Arena<Delimiter<'a, 'd>>,
78109
callback: Option<&'subj mut Callback<'c>>,
79110
) -> Self {
@@ -1066,7 +1097,7 @@ impl<'a, 'r, 'o, 'd, 'i, 'c, 'subj> Subject<'a, 'r, 'o, 'd, 'i, 'c, 'subj> {
10661097
// Need to normalize both to lookup in refmap and to call callback
10671098
lab = strings::normalize_label(&lab);
10681099
let mut reff = if found_label {
1069-
self.refmap.get(&lab).cloned()
1100+
self.refmap.lookup(&lab)
10701101
} else {
10711102
None
10721103
};

src/parser/mod.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ use typed_arena::Arena;
2727

2828
use crate::adapters::HeadingAdapter;
2929

30+
use self::inlines::RefMap;
31+
3032
const TAB_STOP: usize = 4;
3133
const CODE_INDENT: usize = 4;
3234

@@ -114,7 +116,7 @@ type Callback<'c> = &'c mut dyn FnMut(&[u8]) -> Option<(Vec<u8>, Vec<u8>)>;
114116

115117
pub struct Parser<'a, 'o, 'c> {
116118
arena: &'a Arena<AstNode<'a>>,
117-
refmap: HashMap<Vec<u8>, Reference>,
119+
refmap: RefMap,
118120
root: &'a AstNode<'a>,
119121
current: &'a AstNode<'a>,
120122
line_number: u32,
@@ -128,6 +130,7 @@ pub struct Parser<'a, 'o, 'c> {
128130
partially_consumed_tab: bool,
129131
last_line_length: usize,
130132
last_buffer_ended_with_cr: bool,
133+
total_size: usize,
131134
options: &'o ComrakOptions,
132135
callback: Option<Callback<'c>>,
133136
}
@@ -586,7 +589,7 @@ impl<'a, 'o, 'c> Parser<'a, 'o, 'c> {
586589
) -> Self {
587590
Parser {
588591
arena,
589-
refmap: HashMap::new(),
592+
refmap: RefMap::new(),
590593
root,
591594
current: root,
592595
line_number: 0,
@@ -600,6 +603,7 @@ impl<'a, 'o, 'c> Parser<'a, 'o, 'c> {
600603
partially_consumed_tab: false,
601604
last_line_length: 0,
602605
last_buffer_ended_with_cr: false,
606+
total_size: 0,
603607
options,
604608
callback,
605609
}
@@ -609,6 +613,12 @@ impl<'a, 'o, 'c> Parser<'a, 'o, 'c> {
609613
let mut buffer = 0;
610614
let s = s.as_bytes();
611615

616+
if s.len() > usize::MAX - self.total_size {
617+
self.total_size = usize::MAX;
618+
} else {
619+
self.total_size += s.len();
620+
}
621+
612622
if self.last_buffer_ended_with_cr && s.len() > 0 && s[0] == b'\n' {
613623
buffer += 1;
614624
}
@@ -1468,6 +1478,13 @@ impl<'a, 'o, 'c> Parser<'a, 'o, 'c> {
14681478
}
14691479

14701480
self.finalize(self.root);
1481+
1482+
self.refmap.max_ref_size = if self.total_size > 100000 {
1483+
self.total_size
1484+
} else {
1485+
100000
1486+
};
1487+
14711488
self.process_inlines();
14721489
if self.options.extension.footnotes {
14731490
self.process_footnotes();
@@ -1877,7 +1894,7 @@ impl<'a, 'o, 'c> Parser<'a, 'o, 'c> {
18771894

18781895
lab = strings::normalize_label(&lab);
18791896
if !lab.is_empty() {
1880-
subj.refmap.entry(lab.to_vec()).or_insert(Reference {
1897+
subj.refmap.map.entry(lab.to_vec()).or_insert(Reference {
18811898
url: strings::clean_url(&url),
18821899
title: strings::clean_title(&title),
18831900
});

src/strings.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::ctype::{ispunct, isspace};
22
use crate::entity;
33
use crate::parser::AutolinkType;
4+
#[cfg(feature = "syntect")]
45
use std::collections::HashMap;
56
use std::ptr;
67
use std::str;

0 commit comments

Comments
 (0)