From a3b369636fe4b6118ca2017c25a753276a0d6d2b Mon Sep 17 00:00:00 2001 From: noahskelton Date: Tue, 7 Jul 2026 20:54:18 +0200 Subject: [PATCH] Fix out-of-bounds panic when a meta content value ends in a bare charset token extract_a_character_encoding_from_a_meta_element indexed one byte past the end of the input when the content value ended in "charset" with optional trailing whitespace and no "=" after it (e.g. content="text/html; charset"). Guard the step-4 lookahead with .get() and return None when the input ends there. --- html5ever/src/encoding.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/html5ever/src/encoding.rs b/html5ever/src/encoding.rs index 19f58459..410820de 100644 --- a/html5ever/src/encoding.rs +++ b/html5ever/src/encoding.rs @@ -36,8 +36,11 @@ pub(crate) fn extract_a_character_encoding_from_a_meta_element( // Step 4. If the next character is not a U+003D EQUALS SIGN (=), then move position to point just before // that next character, and jump back to the step labeled loop. - if input.as_bytes()[position] == b'=' { - break; + match input.as_bytes().get(position) { + Some(b'=') => break, + Some(_) => {}, + // The input ends after "charset" (plus optional whitespace), so there is no encoding. + None => return None, } } // Skip the "=" @@ -107,6 +110,26 @@ mod tests { ); } + #[test] + fn meta_element_charset_at_end_does_not_panic() { + // "charset" with nothing after it: position advances to input.len(). + assert_eq!( + extract_a_character_encoding_from_a_meta_element(StrTendril::from_slice( + "text/html; charset" + )), + None + ); + assert_eq!( + extract_a_character_encoding_from_a_meta_element(StrTendril::from_slice("charset")), + None + ); + // Trailing whitespace after "charset" must also be safe. + assert_eq!( + extract_a_character_encoding_from_a_meta_element(StrTendril::from_slice("charset \t")), + None + ); + } + #[test] fn meta_element_with_whitespace_around_equals() { assert_eq!(