Bug 1344209: Handle empty strings gracefully in rust nsString bindings. r?mystor draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 03 Mar 2017 15:20:39 +0100
changeset 493202 e3fa38d3bf9b46c1e3941e6a659ec44b44148b72
parent 490254 ecfee5f3896336dba837c2303d0563cc995cafa1
child 547792 9368afec0c02e33cb3c1e3a89ec5f99db1eb9296
push id47684
push userbmo:emilio+bugs@crisal.io
push dateFri, 03 Mar 2017 16:05:20 +0000
reviewersmystor
bugs1344209
milestone54.0a1
Bug 1344209: Handle empty strings gracefully in rust nsString bindings. r?mystor MozReview-Commit-ID: 5lI8LXwZIML
xpcom/rust/nsstring/gtest/Test.cpp
xpcom/rust/nsstring/gtest/test.rs
xpcom/rust/nsstring/src/lib.rs
--- a/xpcom/rust/nsstring/gtest/Test.cpp
+++ b/xpcom/rust/nsstring/gtest/Test.cpp
@@ -124,8 +124,13 @@ extern "C" void Rust_AutoAssignFromCpp()
 TEST(RustNsString, AutoAssignFromCpp) {
   Rust_AutoAssignFromCpp();
 }
 
 extern "C" void Rust_StringWrite();
 TEST(RustNsString, StringWrite) {
   Rust_StringWrite();
 }
+
+extern "C" void Rust_FromEmptyRustString();
+TEST(RustNsString, FromEmptyRustString) {
+  Rust_FromEmptyRustString();
+}
--- a/xpcom/rust/nsstring/gtest/test.rs
+++ b/xpcom/rust/nsstring/gtest/test.rs
@@ -105,8 +105,14 @@ pub extern fn Rust_StringWrite() {
     expect_eq!(s, "abc");
     expect_eq!(cs, "abc");
     write!(s, "{}", 123).unwrap();
     write!(cs, "{}", 123).unwrap();
     expect_eq!(s, "abc123");
     expect_eq!(cs, "abc123");
 }
 
+#[no_mangle]
+pub extern fn Rust_FromEmptyRustString() {
+    let mut test = nsString::from("Blah");
+    test.assign_utf8(&nsCString::from(String::new()));
+    assert!(test.is_empty());
+}
--- a/xpcom/rust/nsstring/src/lib.rs
+++ b/xpcom/rust/nsstring/src/lib.rs
@@ -308,28 +308,32 @@ macro_rules! define_string_types {
             }
         }
 
         impl<'a> From<&'a [$char_t]> for $String<'a> {
             fn from(s: &'a [$char_t]) -> $String<'a> {
                 assert!(s.len() < (u32::MAX as usize));
                 $String {
                     hdr: $StringRepr {
-                        data: s.as_ptr(),
+                        data: if s.is_empty() { ptr::null() } else { s.as_ptr() },
                         length: s.len() as u32,
                         flags: F_NONE,
                     },
                     _marker: PhantomData,
                 }
             }
         }
 
         impl From<Box<[$char_t]>> for $String<'static> {
             fn from(s: Box<[$char_t]>) -> $String<'static> {
                 assert!(s.len() < (u32::MAX as usize));
+                if s.is_empty() {
+                    return $String::new();
+                }
+
                 // SAFETY NOTE: This method produces an F_OWNED ns[C]String from
                 // a Box<[$char_t]>. this is only safe because in the Gecko
                 // tree, we use the same allocator for Rust code as for C++
                 // code, meaning that our box can be legally freed with
                 // libc::free().
                 let length = s.len() as u32;
                 let ptr = s.as_ptr();
                 mem::forget(s);