Bug 1344209: Handle empty strings gracefully in rust nsString bindings. r?mystor
MozReview-Commit-ID: 5lI8LXwZIML
--- 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);