From 06222c277eada351309f0f477368e65a6d347a2d Mon Sep 17 00:00:00 2001 From: mgros Date: Fri, 7 Aug 2026 01:49:18 +0200 Subject: [PATCH 1/4] regex is buggy, and xml comments are ignored by parser anyway --- src/interface.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index 317d7ce2..ebf2d7be 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -178,7 +178,6 @@ pub fn set_mathml(mathml_str: impl AsRef) -> Result { // Strip out processing instructions and comments -- these are not MathML and can cause DOS problems in the parser static PROCESSING_INSTRUCTION: LazyLock = LazyLock::new(|| Regex::new(r#"<\?[\s\S]{1,2048}\?>"#).unwrap()); - static XML_COMMENT: LazyLock = LazyLock::new(|| Regex::new(r#"(?s)"#).unwrap()); // These have some length limits to avoid DOS attacks via long strings static NAMESPACE_DECL: LazyLock = LazyLock::new(|| Regex::new(r#"xmlns:[[:alpha:]]{1,32}"#).unwrap()); @@ -204,7 +203,6 @@ pub fn set_mathml(mathml_str: impl AsRef) -> Result { let mut error_message = "".to_string(); // can't return a result inside the replace_all, so we do this hack of setting the message and then returning the error - let mathml_str = XML_COMMENT.replace_all(mathml_str, ""); let mathml_str = PROCESSING_INSTRUCTION.replace_all(&mathml_str, ""); // FIX: need to deal with character data and convert to something the parser knows let mathml_str = HTML_ENTITIES.replace_all(&mathml_str, |cap: &Captures| match HTML_ENTITIES_MAPPING.get(&cap[1]) { From 3162cff3c0e9d5b185845950324852b7808691b9 Mon Sep 17 00:00:00 2001 From: mgros Date: Tue, 11 Aug 2026 02:53:46 +0200 Subject: [PATCH 2/4] fix cargo clippy --- src/interface.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface.rs b/src/interface.rs index ebf2d7be..b0eb00e1 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -203,7 +203,7 @@ pub fn set_mathml(mathml_str: impl AsRef) -> Result { let mut error_message = "".to_string(); // can't return a result inside the replace_all, so we do this hack of setting the message and then returning the error - let mathml_str = PROCESSING_INSTRUCTION.replace_all(&mathml_str, ""); + let mathml_str = PROCESSING_INSTRUCTION.replace_all(mathml_str, ""); // FIX: need to deal with character data and convert to something the parser knows let mathml_str = HTML_ENTITIES.replace_all(&mathml_str, |cap: &Captures| match HTML_ENTITIES_MAPPING.get(&cap[1]) { None => { From 9f10aaee1ba76ef9933d8f7a5437db0fbb6514d1 Mon Sep 17 00:00:00 2001 From: NSoiffer Date: Tue, 11 Aug 2026 20:48:53 -0700 Subject: [PATCH 3/4] Remove processing instruction regex to enhance security Removed the static regex for processing instructions and comments. `sxd_parser` handles these and the earlier size limit prevents DOS attacks. All but elements and text children are eliminated from the DOM in `cleanup_mathml`. --- src/interface.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index b0eb00e1..98ff8c5e 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -176,9 +176,6 @@ pub fn set_mathml(mathml_str: impl AsRef) -> Result { static MATHJAX_V2: LazyLock = LazyLock::new(|| Regex::new(r#"class *= *['"]MJX-.*?['"]"#).unwrap()); static MATHJAX_V3: LazyLock = LazyLock::new(|| Regex::new(r#"class *= *['"]data-mjx-.*?['"]"#).unwrap()); - // Strip out processing instructions and comments -- these are not MathML and can cause DOS problems in the parser - static PROCESSING_INSTRUCTION: LazyLock = LazyLock::new(|| Regex::new(r#"<\?[\s\S]{1,2048}\?>"#).unwrap()); - // These have some length limits to avoid DOS attacks via long strings static NAMESPACE_DECL: LazyLock = LazyLock::new(|| Regex::new(r#"xmlns:[[:alpha:]]{1,32}"#).unwrap()); static PREFIX: LazyLock = LazyLock::new(|| Regex::new(r#"() -> Result { let mut error_message = "".to_string(); // can't return a result inside the replace_all, so we do this hack of setting the message and then returning the error - let mathml_str = PROCESSING_INSTRUCTION.replace_all(mathml_str, ""); // FIX: need to deal with character data and convert to something the parser knows let mathml_str = HTML_ENTITIES.replace_all(&mathml_str, |cap: &Captures| match HTML_ENTITIES_MAPPING.get(&cap[1]) { None => { From fb70b93e317008319c0ae13606aca114af659059 Mon Sep 17 00:00:00 2001 From: NSoiffer Date: Tue, 11 Aug 2026 20:51:28 -0700 Subject: [PATCH 4/4] Correct variable reference in HTML_ENTITIES replacement Fix the usage of mathml_str in HTML_ENTITIES replacement. --- src/interface.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interface.rs b/src/interface.rs index 98ff8c5e..617a259b 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -201,7 +201,7 @@ pub fn set_mathml(mathml_str: impl AsRef) -> Result { let mut error_message = "".to_string(); // can't return a result inside the replace_all, so we do this hack of setting the message and then returning the error // FIX: need to deal with character data and convert to something the parser knows - let mathml_str = HTML_ENTITIES.replace_all(&mathml_str, |cap: &Captures| match HTML_ENTITIES_MAPPING.get(&cap[1]) { + let mathml_str = HTML_ENTITIES.replace_all(mathml_str, |cap: &Captures| match HTML_ENTITIES_MAPPING.get(&cap[1]) { None => { error_message = format!("No entity named '{}'", &cap[0]); cap[0].to_string()