diff options
-rw-r--r-- | components/script/dom/bindings/conversions.rs | 28 | ||||
-rw-r--r-- | components/script/lib.rs | 2 | ||||
-rw-r--r-- | components/util/opts.rs | 9 |
3 files changed, 37 insertions, 2 deletions
diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index 9967b6cf9b7..9f6ed02a289 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -352,10 +352,34 @@ pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString { JS_GetTwoByteStringCharsAndLength(cx, ptr::null(), s, &mut length) }; assert!(!chars.is_null()); - let char_vec = unsafe { + let potentially_ill_formed_utf16 = unsafe { slice::from_raw_parts(chars as *const u16, length as usize) }; - String::from_utf16(char_vec).unwrap() + let mut s = String::with_capacity(length as usize); + for item in ::rustc_unicode::str::utf16_items(potentially_ill_formed_utf16) { + use ::rustc_unicode::str::Utf16Item::*; + match item { + ScalarValue(c) => s.push(c), + LoneSurrogate(_) => { + // FIXME: Add more info like document URL in the message? + macro_rules! message { + () => { + "Found an unpaired surrogate in a DOM string. \ + If you see this in real web content, \ + please comment on https://github.com/servo/servo/issues/6564" + } + } + if ::util::opts::get().replace_surrogates { + error!(message!()); + s.push('\u{FFFD}'); + } else { + panic!(concat!(message!(), " Use `-Z replace-surrogates` \ + on the command line to make this non-fatal.")); + } + } + } + } + s } } diff --git a/components/script/lib.rs b/components/script/lib.rs index 6b3f5ce8c8f..15a1c4c5db5 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -21,6 +21,7 @@ #![feature(rc_unique)] #![feature(slice_chars)] #![feature(str_utf16)] +#![feature(unicode)] #![feature(vec_push_all)] #![deny(unsafe_code)] @@ -49,6 +50,7 @@ extern crate msg; extern crate net_traits; extern crate num; extern crate rustc_serialize; +extern crate rustc_unicode; extern crate time; extern crate canvas; extern crate canvas_traits; diff --git a/components/util/opts.rs b/components/util/opts.rs index 0a767848268..9ba7f86a6d2 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -69,6 +69,11 @@ pub struct Opts { pub userscripts: Option<String>, pub output_file: Option<String>, + + /// Replace unpaires surrogates in DOM strings with U+FFFD. + /// See https://github.com/servo/servo/issues/6564 + pub replace_surrogates: bool, + pub headless: bool, pub hard_fail: bool, @@ -187,6 +192,8 @@ pub fn print_debug_usage(app: &str) -> ! { print_option("disable-share-style-cache", "Disable the style sharing cache."); print_option("parallel-display-list-building", "Build display lists in parallel."); + print_option("replace-surrogates", "Replace unpaires surrogates in DOM strings with U+FFFD. \ + See https://github.com/servo/servo/issues/6564"); println!(""); @@ -223,6 +230,7 @@ pub fn default_opts() -> Opts { nossl: false, userscripts: None, output_file: None, + replace_surrogates: false, headless: true, hard_fail: true, bubble_inline_sizes_separately: false, @@ -397,6 +405,7 @@ pub fn from_cmdline_args(args: &[String]) { nossl: nossl, userscripts: opt_match.opt_default("userscripts", ""), output_file: opt_match.opt_str("o"), + replace_surrogates: debug_options.contains(&"replace-surrogates"), headless: opt_match.opt_present("z"), hard_fail: opt_match.opt_present("f"), bubble_inline_sizes_separately: bubble_inline_sizes_separately, |