Guard against unbounded paren nesting inside links
@@ -31,6 +31,13 @@ use crate::scanners::*;
use crate::tree::{TreePointer, TreeIndex, Tree};
use crate::linklabel::{scan_link_label, scan_link_label_rest, LinkLabel, ReferenceLabel};
+// Allowing arbitrary depth nested parentheses inside link destinations
+// can create denial of service vulnerabilities if we're not careful.
+// The simplest countermeasure is to limit their depth, which is
+// explicitly allowed by the spec as long as the limit is at least 3:
+// https://spec.commonmark.org/0.28/#link-destination
+const LINK_MAX_NESTED_PARENS: usize = 5;
+
#[derive(Clone, Debug, PartialEq)]
pub enum Tag<'a> {
// block-level tags
@@ -1908,6 +1915,9 @@ fn scan_link_destination_plain<'t, 'a>(scanner: &mut InlineScanner<'t, 'a>) -> O
match c {
'(' => {
nest += 1;
+ if nest > LINK_MAX_NESTED_PARENS {
+ return None;
+ }
}
')' => {
if nest == 0 {
