Bug 1381080 patch 1 - Add ClassFlags::NULL_TERMINATED to strings that require null-termination. r=erahm
authorL. David Baron <dbaron@dbaron.org>
Thu, 20 Jul 2017 15:46:58 -0700
changeset 418718 79bc740e42aaeb256202eef44335a563594a7b04
parent 418717 a4c46cc48c7836ce767ab8897deea0299f61d79c
child 418719 e5e88978e73540cdd60f7a0374ac74b8fcfe0925
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1381080
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1381080 patch 1 - Add ClassFlags::NULL_TERMINATED to strings that require null-termination. r=erahm This is needed for patch 4. MozReview-Commit-ID: 5ikQFIL9O0i
xpcom/rust/nsstring/gtest/Test.cpp
xpcom/rust/nsstring/src/lib.rs
xpcom/string/nsAString.h
xpcom/string/nsTLiteralString.h
xpcom/string/nsTString.h
xpcom/string/nsTSubstring.h
--- a/xpcom/rust/nsstring/gtest/Test.cpp
+++ b/xpcom/rust/nsstring/gtest/Test.cpp
@@ -57,37 +57,41 @@ MEMBER_CHECK(nsFixedCString, mFixedCapac
 MEMBER_CHECK(nsFixedCString, mFixedBuf)
 
 extern "C" void Rust_Test_NsStringFlags(uint16_t* f_terminated,
                                         uint16_t* f_voided,
                                         uint16_t* f_shared,
                                         uint16_t* f_owned,
                                         uint16_t* f_fixed,
                                         uint16_t* f_literal,
-                                        uint16_t* f_class_fixed);
+                                        uint16_t* f_class_fixed,
+                                        uint16_t* f_class_null_terminated);
 TEST(RustNsString, NsStringFlags) {
-  uint16_t f_terminated, f_voided, f_shared, f_owned, f_fixed, f_literal, f_class_fixed;
+  uint16_t f_terminated, f_voided, f_shared, f_owned, f_fixed, f_literal,
+           f_class_fixed, f_class_null_terminated;
   Rust_Test_NsStringFlags(&f_terminated,
                           &f_voided, &f_shared,
                           &f_owned, &f_fixed,
-                          &f_literal, &f_class_fixed);
+                          &f_literal, &f_class_fixed, &f_class_null_terminated);
   EXPECT_EQ(f_terminated, uint16_t(nsAString::DataFlags::TERMINATED));
   EXPECT_EQ(f_terminated, uint16_t(nsACString::DataFlags::TERMINATED));
   EXPECT_EQ(f_voided, uint16_t(nsAString::DataFlags::VOIDED));
   EXPECT_EQ(f_voided, uint16_t(nsACString::DataFlags::VOIDED));
   EXPECT_EQ(f_shared, uint16_t(nsAString::DataFlags::SHARED));
   EXPECT_EQ(f_shared, uint16_t(nsACString::DataFlags::SHARED));
   EXPECT_EQ(f_owned, uint16_t(nsAString::DataFlags::OWNED));
   EXPECT_EQ(f_owned, uint16_t(nsACString::DataFlags::OWNED));
   EXPECT_EQ(f_fixed, uint16_t(nsAString::DataFlags::FIXED));
   EXPECT_EQ(f_fixed, uint16_t(nsACString::DataFlags::FIXED));
   EXPECT_EQ(f_literal, uint16_t(nsAString::DataFlags::LITERAL));
   EXPECT_EQ(f_literal, uint16_t(nsACString::DataFlags::LITERAL));
   EXPECT_EQ(f_class_fixed, uint16_t(nsAString::ClassFlags::FIXED));
   EXPECT_EQ(f_class_fixed, uint16_t(nsACString::ClassFlags::FIXED));
+  EXPECT_EQ(f_class_null_terminated, uint16_t(nsAString::ClassFlags::NULL_TERMINATED));
+  EXPECT_EQ(f_class_null_terminated, uint16_t(nsACString::ClassFlags::NULL_TERMINATED));
 }
 
 extern "C" void Rust_StringFromCpp(const nsACString* aCStr, const nsAString* aStr);
 TEST(RustNsString, StringFromCpp) {
   nsAutoCString foo;
   foo.AssignASCII("Hello, World!");
 
   nsAutoString bar;
--- a/xpcom/rust/nsstring/src/lib.rs
+++ b/xpcom/rust/nsstring/src/lib.rs
@@ -151,17 +151,18 @@ mod data_flags {
 }
 
 mod class_flags {
     bitflags! {
         // While this has the same layout as u16, it cannot be passed
         // over FFI safely as a u16.
         #[repr(C)]
         pub flags ClassFlags : u16 {
-            const FIXED = 1 << 0, // indicates that |this| is of type nsTFixedString
+            const FIXED = 1 << 0, // |this| is of type nsTFixedString
+            const NULL_TERMINATED = 1 << 1, // |this| requires its buffer is null-terminated
         }
     }
 }
 
 use data_flags::DataFlags;
 use class_flags::ClassFlags;
 
 ////////////////////////////////////
@@ -404,17 +405,17 @@ macro_rules! define_string_types {
 
         impl $String<'static> {
             pub fn new() -> $String<'static> {
                 $String {
                     hdr: $StringRepr {
                         data: ptr::null(),
                         length: 0,
                         dataflags: DataFlags::empty(),
-                        classflags: ClassFlags::empty(),
+                        classflags: class_flags::NULL_TERMINATED,
                     },
                     _marker: PhantomData,
                 }
             }
         }
 
         impl<'a> Drop for $String<'a> {
             fn drop(&mut self) {
@@ -458,17 +459,17 @@ 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: if s.is_empty() { ptr::null() } else { s.as_ptr() },
                         length: s.len() as u32,
                         dataflags: DataFlags::empty(),
-                        classflags: ClassFlags::empty(),
+                        classflags: class_flags::NULL_TERMINATED,
                     },
                     _marker: PhantomData,
                 }
             }
         }
 
         impl From<Box<[$char_t]>> for $String<'static> {
             fn from(s: Box<[$char_t]>) -> $String<'static> {
@@ -488,17 +489,17 @@ macro_rules! define_string_types {
                 unsafe {
                     Gecko_IncrementStringAdoptCount(ptr as *mut _);
                 }
                 $String {
                     hdr: $StringRepr {
                         data: ptr,
                         length: length,
                         dataflags: data_flags::OWNED,
-                        classflags: ClassFlags::empty(),
+                        classflags: class_flags::NULL_TERMINATED,
                     },
                     _marker: PhantomData,
                 }
             }
         }
 
         impl From<Vec<$char_t>> for $String<'static> {
             fn from(s: Vec<$char_t>) -> $String<'static> {
@@ -579,17 +580,17 @@ macro_rules! define_string_types {
                 assert!(len < (u32::MAX as usize));
                 let buf_ptr = buf.as_mut_ptr();
                 $FixedString {
                     base: $String {
                         hdr: $StringRepr {
                             data: ptr::null(),
                             length: 0,
                             dataflags: DataFlags::empty(),
-                            classflags: class_flags::FIXED,
+                            classflags: class_flags::FIXED | class_flags::NULL_TERMINATED,
                         },
                         _marker: PhantomData,
                     },
                     capacity: len as u32,
                     buffer: buf_ptr,
                     _marker: PhantomData,
                 }
             }
@@ -1132,20 +1133,22 @@ pub mod test_helpers {
     #[no_mangle]
     #[allow(non_snake_case)]
     pub extern fn Rust_Test_NsStringFlags(f_terminated: *mut u16,
                                           f_voided: *mut u16,
                                           f_shared: *mut u16,
                                           f_owned: *mut u16,
                                           f_fixed: *mut u16,
                                           f_literal: *mut u16,
-                                          f_class_fixed: *mut u16) {
+                                          f_class_fixed: *mut u16,
+                                          f_class_null_terminated: *mut u16) {
         unsafe {
             *f_terminated = data_flags::TERMINATED.bits();
             *f_voided = data_flags::VOIDED.bits();
             *f_shared = data_flags::SHARED.bits();
             *f_owned = data_flags::OWNED.bits();
             *f_fixed = data_flags::FIXED.bits();
             *f_literal = data_flags::LITERAL.bits();
             *f_class_fixed = class_flags::FIXED.bits();
+            *f_class_null_terminated = class_flags::NULL_TERMINATED.bits();
         }
     }
 }
--- a/xpcom/string/nsAString.h
+++ b/xpcom/string/nsAString.h
@@ -65,17 +65,18 @@ enum class StringDataFlags : uint16_t
   OWNED        = 1 << 3,  // mData points to a heap-allocated, raw buffer
   FIXED        = 1 << 4,  // mData points to a fixed-size writable, dependent buffer
   LITERAL      = 1 << 5   // mData points to a string literal; DataFlags::TERMINATED will also be set
 };
 
 // bits for mClassFlags
 enum class StringClassFlags : uint16_t
 {
-  FIXED  = 1 << 0   // indicates that |this| is of type nsTFixedString
+  FIXED           = 1 << 0, // |this| is of type nsTFixedString
+  NULL_TERMINATED = 1 << 1  // |this| requires its buffer is null-terminated
 };
 
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(StringDataFlags)
 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(StringClassFlags)
 
 } // namespace detail
 } // namespace mozilla
 
--- a/xpcom/string/nsTLiteralString.h
+++ b/xpcom/string/nsTLiteralString.h
@@ -25,17 +25,18 @@ public:
 
   /**
    * constructor
    */
 
   template<size_type N>
   explicit nsTLiteralString_CharT(const char_type (&aStr)[N])
     : base_string_type(const_cast<char_type*>(aStr), N - 1,
-                       DataFlags::TERMINATED | DataFlags::LITERAL, ClassFlags(0))
+                       DataFlags::TERMINATED | DataFlags::LITERAL,
+                       ClassFlags::NULL_TERMINATED)
   {
   }
 
   /**
    * For compatibility with existing code that requires const ns[C]String*.
    * Use sparingly. If possible, rewrite code to use const ns[C]String&
    * and the implicit cast will just work.
    */
--- a/xpcom/string/nsTString.h
+++ b/xpcom/string/nsTString.h
@@ -25,51 +25,51 @@ public:
 
 public:
 
   /**
    * constructors
    */
 
   nsTString_CharT()
-    : substring_type()
+    : substring_type(ClassFlags::NULL_TERMINATED)
   {
   }
 
   explicit
   nsTString_CharT(const char_type* aData, size_type aLength = size_type(-1))
-    : substring_type()
+    : substring_type(ClassFlags::NULL_TERMINATED)
   {
     Assign(aData, aLength);
   }
 
 #if defined(CharT_is_PRUnichar) && defined(MOZ_USE_CHAR16_WRAPPER)
   explicit
   nsTString_CharT(char16ptr_t aStr, size_type aLength = size_type(-1))
-    : substring_type()
+    : substring_type(ClassFlags::NULL_TERMINATED)
   {
     Assign(static_cast<const char16_t*>(aStr), aLength);
   }
 #endif
 
   nsTString_CharT(const self_type& aStr)
-    : substring_type()
+    : substring_type(ClassFlags::NULL_TERMINATED)
   {
     Assign(aStr);
   }
 
   MOZ_IMPLICIT nsTString_CharT(const substring_tuple_type& aTuple)
-    : substring_type()
+    : substring_type(ClassFlags::NULL_TERMINATED)
   {
     Assign(aTuple);
   }
 
   explicit
   nsTString_CharT(const substring_type& aReadable)
-    : substring_type()
+    : substring_type(ClassFlags::NULL_TERMINATED)
   {
     Assign(aReadable);
   }
 
 
   // |operator=| does not inherit, so we must define our own
   self_type& operator=(char_type aChar)
   {
@@ -461,17 +461,18 @@ public:
   }
 
 
 protected:
 
   // allow subclasses to initialize fields directly
   nsTString_CharT(char_type* aData, size_type aLength, DataFlags aDataFlags,
                   ClassFlags aClassFlags)
-    : substring_type(aData, aLength, aDataFlags, aClassFlags)
+    : substring_type(aData, aLength, aDataFlags,
+                     aClassFlags | ClassFlags::NULL_TERMINATED)
   {
   }
 
   struct Segment {
     uint32_t mBegin, mLength;
     Segment(uint32_t aBegin, uint32_t aLength)
       : mBegin(aBegin)
       , mLength(aLength)
--- a/xpcom/string/nsTSubstring.h
+++ b/xpcom/string/nsTSubstring.h
@@ -1054,16 +1054,23 @@ protected:
   // (NOTE: this is for internal use only)
   nsTSubstring_CharT(const self_type& aStr)
     : nsTStringRepr_CharT(aStr.mData, aStr.mLength,
                           aStr.mDataFlags & (DataFlags::TERMINATED | DataFlags::VOIDED),
                           ClassFlags(0))
   {
   }
 
+  // initialization with ClassFlags
+  explicit nsTSubstring_CharT(ClassFlags aClassFlags)
+    : nsTStringRepr_CharT(char_traits::sEmptyBuffer, 0, DataFlags::TERMINATED,
+                          aClassFlags)
+  {
+  }
+
  /**
    * allows for direct initialization of a nsTSubstring object.
    */
   nsTSubstring_CharT(char_type* aData, size_type aLength,
                      DataFlags aDataFlags, ClassFlags aClassFlags)
 // XXXbz or can I just include nscore.h and use NS_BUILD_REFCNT_LOGGING?
 #if defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING)
 #define XPCOM_STRING_CONSTRUCTOR_OUT_OF_LINE