Bug 1484045 - Prohibit shrinking of the string's buffer in appends of Latin1 to UTF-16 and vice versa. r=froydnj
authorHenri Sivonen <hsivonen@hsivonen.fi>
Tue, 28 Aug 2018 14:13:17 +0000
changeset 488696 9494c03553b9b968194c78602fb75273d39d9ede
parent 488695 8e03f957959dad0e0da538d975b60cf650237c3e
child 488697 48ca12e943f5f8514dcc01e4ba9ec1888dce8485
child 488778 3205543f957cd2a6905486d73aa897535fdd9825
push id9734
push usershindli@mozilla.com
push dateThu, 30 Aug 2018 12:18:07 +0000
treeherdermozilla-beta@71c71ab3afae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1484045
milestone63.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 1484045 - Prohibit shrinking of the string's buffer in appends of Latin1 to UTF-16 and vice versa. r=froydnj This restores the old allocation semantics for "append" operations between Latin1 and UTF-16 while keeping the buffer re-use optimization for the "assign" cases. MozReview-Commit-ID: 8JCw3AaCNLN Differential Revision: https://phabricator.services.mozilla.com/D3582
servo/support/gecko/nsstring/src/conversions.rs
xpcom/string/nsReadableUtils.h
--- a/servo/support/gecko/nsstring/src/conversions.rs
+++ b/servo/support/gecko/nsstring/src/conversions.rs
@@ -134,20 +134,20 @@ macro_rules! shrinking_conversion {
 ///
 /// `$name` is the name of the function to generate
 /// `$convert` is the underlying `encoding_rs::mem` function to use
 /// `$other_ty` is the type of the input slice
 macro_rules! constant_conversion {
     (name = $name:ident,
      convert = $convert:ident,
      other_ty = $other_ty:ty) => (
-        fn $name(&mut self, other: $other_ty, old_len: usize) -> Result<BulkWriteOk, ()> {
+        fn $name(&mut self, other: $other_ty, old_len: usize, allow_shrinking: bool) -> Result<BulkWriteOk, ()> {
             let new_len = old_len.checked_add(other.len()).ok_or(())?;
             let mut handle = unsafe {
-                self.bulk_write(new_len, old_len, true)?
+                self.bulk_write(new_len, old_len, allow_shrinking)?
             };
             $convert(other, &mut handle.as_mut_slice()[old_len..]);
             Ok(handle.finish(new_len, false))
         }
      )
 }
 
 /// An intermediate check for avoiding a copy and having an `nsStringBuffer`
@@ -276,40 +276,40 @@ impl nsAString {
         name = fallible_append_latin1_impl,
         convert = convert_latin1_to_utf16,
         other_ty = &[u8]
     );
 
     /// Convert a Latin1 (i.e. byte value equals scalar value; not windows-1252!)
     /// into UTF-16 and replace the content of this string with the conversion result.
     pub fn assign_latin1(&mut self, other: &[u8]) {
-        self.fallible_append_latin1_impl(other, 0)
+        self.fallible_append_latin1_impl(other, 0, true)
             .expect("Out of memory");
     }
 
     /// Convert a Latin1 (i.e. byte value equals scalar value; not windows-1252!)
     /// into UTF-16 and fallibly replace the content of this string with the
     /// conversion result.
     pub fn fallible_assign_latin1(&mut self, other: &[u8]) -> Result<(), ()> {
-        self.fallible_append_latin1_impl(other, 0).map(|_| ())
+        self.fallible_append_latin1_impl(other, 0, true).map(|_| ())
     }
 
     /// Convert a Latin1 (i.e. byte value equals scalar value; not windows-1252!)
     /// into UTF-16 and append the conversion result to this string.
     pub fn append_latin1(&mut self, other: &[u8]) {
         let len = self.len();
-        self.fallible_append_latin1_impl(other, len)
+        self.fallible_append_latin1_impl(other, len, false)
             .expect("Out of memory");
     }
 
     /// Convert a Latin1 (i.e. byte value equals scalar value; not windows-1252!)
     /// into UTF-16 and fallibly append the conversion result to this string.
     pub fn fallible_append_latin1(&mut self, other: &[u8]) -> Result<(), ()> {
         let len = self.len();
-        self.fallible_append_latin1_impl(other, len).map(|_| ())
+        self.fallible_append_latin1_impl(other, len, false).map(|_| ())
     }
 }
 
 impl nsACString {
     // UTF-16 to UTF-8
 
     fn fallible_append_utf16_to_utf8_impl(
         &mut self,
@@ -410,64 +410,64 @@ impl nsACString {
     ///
     /// # Panics
     ///
     /// If the input contains code points above U+00FF or is not valid UTF-16,
     /// panics in debug mode and produces garbage in a memory-safe way in
     /// release builds. The nature of the garbage may differ based on CPU
     /// architecture and must not be relied upon.
     pub fn assign_utf16_to_latin1_lossy(&mut self, other: &[u16]) {
-        self.fallible_append_utf16_to_latin1_lossy_impl(other, 0)
+        self.fallible_append_utf16_to_latin1_lossy_impl(other, 0, true)
             .expect("Out of memory");
     }
 
     /// Convert a UTF-16 string whose all code points are below U+0100 into
     /// a Latin1 (scalar value is byte value; not windows-1252!) string and
     /// fallibly replace the content of this string with the conversion result.
     ///
     /// # Panics
     ///
     /// If the input contains code points above U+00FF or is not valid UTF-16,
     /// panics in debug mode and produces garbage in a memory-safe way in
     /// release builds. The nature of the garbage may differ based on CPU
     /// architecture and must not be relied upon.
     pub fn fallible_assign_utf16_to_latin1_lossy(&mut self, other: &[u16]) -> Result<(), ()> {
-        self.fallible_append_utf16_to_latin1_lossy_impl(other, 0)
+        self.fallible_append_utf16_to_latin1_lossy_impl(other, 0, true)
             .map(|_| ())
     }
 
     /// Convert a UTF-16 string whose all code points are below U+0100 into
     /// a Latin1 (scalar value is byte value; not windows-1252!) string and
     /// append the conversion result to this string.
     ///
     /// # Panics
     ///
     /// If the input contains code points above U+00FF or is not valid UTF-16,
     /// panics in debug mode and produces garbage in a memory-safe way in
     /// release builds. The nature of the garbage may differ based on CPU
     /// architecture and must not be relied upon.
     pub fn append_utf16_to_latin1_lossy(&mut self, other: &[u16]) {
         let len = self.len();
-        self.fallible_append_utf16_to_latin1_lossy_impl(other, len)
+        self.fallible_append_utf16_to_latin1_lossy_impl(other, len, false)
             .expect("Out of memory");
     }
 
     /// Convert a UTF-16 string whose all code points are below U+0100 into
     /// a Latin1 (scalar value is byte value; not windows-1252!) string and
     /// fallibly append the conversion result to this string.
     ///
     /// # Panics
     ///
     /// If the input contains code points above U+00FF or is not valid UTF-16,
     /// panics in debug mode and produces garbage in a memory-safe way in
     /// release builds. The nature of the garbage may differ based on CPU
     /// architecture and must not be relied upon.
     pub fn fallible_append_utf16_to_latin1_lossy(&mut self, other: &[u16]) -> Result<(), ()> {
         let len = self.len();
-        self.fallible_append_utf16_to_latin1_lossy_impl(other, len)
+        self.fallible_append_utf16_to_latin1_lossy_impl(other, len, false)
             .map(|_| ())
     }
 
     // UTF-8 to Latin1
 
     ascii_copy_avoidance!(
         name = fallible_append_utf8_to_latin1_lossy_check,
         implementation = fallible_append_utf8_to_latin1_lossy_impl,
@@ -687,20 +687,21 @@ pub unsafe extern "C" fn nsstring_fallib
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn nsstring_fallible_append_latin1_impl(
     this: *mut nsAString,
     other: *const u8,
     other_len: usize,
     old_len: usize,
+    allow_shrinking: bool,
 ) -> bool {
     let other_slice = slice::from_raw_parts(other, other_len);
     (*this)
-        .fallible_append_latin1_impl(other_slice, old_len)
+        .fallible_append_latin1_impl(other_slice, old_len, allow_shrinking)
         .is_ok()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn nscstring_fallible_append_utf16_to_utf8_impl(
     this: *mut nsACString,
     other: *const u16,
     other_len: usize,
@@ -713,20 +714,21 @@ pub unsafe extern "C" fn nscstring_falli
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn nscstring_fallible_append_utf16_to_latin1_lossy_impl(
     this: *mut nsACString,
     other: *const u16,
     other_len: usize,
     old_len: usize,
+    allow_shrinking: bool,
 ) -> bool {
     let other_slice = slice::from_raw_parts(other, other_len);
     (*this)
-        .fallible_append_utf16_to_latin1_lossy_impl(other_slice, old_len)
+        .fallible_append_utf16_to_latin1_lossy_impl(other_slice, old_len, allow_shrinking)
         .is_ok()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn nscstring_fallible_append_utf8_to_latin1_lossy_check(
     this: *mut nsACString,
     other: *const nsACString,
     old_len: usize,
--- a/xpcom/string/nsReadableUtils.h
+++ b/xpcom/string/nsReadableUtils.h
@@ -83,29 +83,31 @@ extern "C" {
                                      const char* aOther,
                                      size_t aOtherLen,
                                      size_t aOldLen);
 
   bool
   nsstring_fallible_append_latin1_impl(nsAString* aThis,
                                        const char* aOther,
                                        size_t aOtherLen,
-                                       size_t aOldLen);
+                                       size_t aOldLen,
+                                       bool aAllowShrinking);
 
   bool
   nscstring_fallible_append_utf16_to_utf8_impl(nsACString* aThis,
                                                const char16_t*,
                                                size_t aOtherLen,
                                                size_t aOldLen);
 
   bool
   nscstring_fallible_append_utf16_to_latin1_lossy_impl(nsACString* aThis,
                                                        const char16_t*,
                                                        size_t aOtherLen,
-                                                       size_t aOldLen);
+                                                       size_t aOldLen,
+                                                       bool aAllowShrinking);
 
   bool
   nscstring_fallible_append_utf8_to_latin1_lossy_check(nsACString* aThis,
                                                        const nsACString* aOther,
                                                        size_t aOldLen);
 
   bool
   nscstring_fallible_append_latin1_to_utf8_check(nsACString* aThis,
@@ -251,34 +253,34 @@ AppendUTF8toUTF16(mozilla::Span<const ch
 // legacy reasons.
 
 inline MOZ_MUST_USE bool
 CopyASCIItoUTF16(mozilla::Span<const char> aSource,
                  nsAString& aDest,
                  const mozilla::fallible_t&)
 {
   return nsstring_fallible_append_latin1_impl(
-    &aDest, aSource.Elements(), aSource.Length(), 0);
+    &aDest, aSource.Elements(), aSource.Length(), 0, true);
 }
 
 inline void
 CopyASCIItoUTF16(mozilla::Span<const char> aSource, nsAString& aDest)
 {
   if (MOZ_UNLIKELY(!CopyASCIItoUTF16(aSource, aDest, mozilla::fallible))) {
     aDest.AllocFailed(aSource.Length());
   }
 }
 
 inline MOZ_MUST_USE bool
 AppendASCIItoUTF16(mozilla::Span<const char> aSource,
                    nsAString& aDest,
                    const mozilla::fallible_t&)
 {
   return nsstring_fallible_append_latin1_impl(
-    &aDest, aSource.Elements(), aSource.Length(), aDest.Length());
+    &aDest, aSource.Elements(), aSource.Length(), aDest.Length(), false);
 }
 
 inline void
 AppendASCIItoUTF16(mozilla::Span<const char> aSource, nsAString& aDest)
 {
   if (MOZ_UNLIKELY(!AppendASCIItoUTF16(aSource, aDest, mozilla::fallible))) {
     aDest.AllocFailed(aDest.Length() + aSource.Length());
   }
@@ -330,34 +332,34 @@ AppendUTF16toUTF8(mozilla::Span<const ch
 // "ASCII" instead of "Latin1" for legacy reasons.
 
 inline MOZ_MUST_USE bool
 LossyCopyUTF16toASCII(mozilla::Span<const char16_t> aSource,
                       nsACString& aDest,
                       const mozilla::fallible_t&)
 {
   return nscstring_fallible_append_utf16_to_latin1_lossy_impl(
-    &aDest, aSource.Elements(), aSource.Length(), 0);
+    &aDest, aSource.Elements(), aSource.Length(), 0, true);
 }
 
 inline void
 LossyCopyUTF16toASCII(mozilla::Span<const char16_t> aSource, nsACString& aDest)
 {
   if (MOZ_UNLIKELY(!LossyCopyUTF16toASCII(aSource, aDest, mozilla::fallible))) {
     aDest.AllocFailed(aSource.Length());
   }
 }
 
 inline MOZ_MUST_USE bool
 LossyAppendUTF16toASCII(mozilla::Span<const char16_t> aSource,
                         nsACString& aDest,
                         const mozilla::fallible_t&)
 {
   return nscstring_fallible_append_utf16_to_latin1_lossy_impl(
-    &aDest, aSource.Elements(), aSource.Length(), aDest.Length());
+    &aDest, aSource.Elements(), aSource.Length(), aDest.Length(), false);
 }
 
 inline void
 LossyAppendUTF16toASCII(mozilla::Span<const char16_t> aSource,
                         nsACString& aDest)
 {
   if (MOZ_UNLIKELY(
         !LossyAppendUTF16toASCII(aSource, aDest, mozilla::fallible))) {