Bug 1493441 - Make XDRState::codeChars(char16_t*, size_t) perform buffer-alignment before acting so that its callers don't have to do so manually. r=tcampbell
authorJeff Walden <jwalden@mit.edu>
Tue, 25 Sep 2018 16:35:43 -0400
changeset 489356 acd510f0152a9c4624fafa7eceda552be1a6c376
parent 489355 d912f4d60ea470d68383eb2f011993700bf4f7bf
child 489357 f7c32e7abf7293b99c6d1941af6e15ebc3119d5c
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewerstcampbell
bugs1493441
milestone64.0a1
Bug 1493441 - Make XDRState::codeChars(char16_t*, size_t) perform buffer-alignment before acting so that its callers don't have to do so manually. r=tcampbell
js/src/vm/JSAtom.cpp
js/src/vm/Xdr.cpp
js/src/vm/Xdr.h
--- a/js/src/vm/JSAtom.cpp
+++ b/js/src/vm/JSAtom.cpp
@@ -1062,22 +1062,16 @@ js::XDRAtom(XDRState<mode>* xdr, Mutable
 
     MOZ_TRY(xdr->codeUint32(&lengthAndEncoding));
 
     if (mode == XDR_DECODE) {
         length = lengthAndEncoding >> 1;
         latin1 = lengthAndEncoding & 0x1;
     }
 
-    // We need to align the string in the XDR buffer such that we can avoid
-    // non-align loads of 16bits characters.
-    if (!latin1) {
-        MOZ_TRY(xdr->codeAlign(sizeof(char16_t)));
-    }
-
     if (mode == XDR_ENCODE) {
         JS::AutoCheckCannotGC nogc;
         if (latin1) {
             return xdr->codeChars(const_cast<JS::Latin1Char*>(atomp->latin1Chars(nogc)),
                                   length);
         }
         return xdr->codeChars(const_cast<char16_t*>(atomp->twoByteChars(nogc)), length);
     }
@@ -1095,17 +1089,23 @@ js::XDRAtom(XDRState<mode>* xdr, Mutable
             chars = reinterpret_cast<const Latin1Char*>(ptr);
         }
         atom = AtomizeChars(cx, chars, length);
     } else {
 #if MOZ_LITTLE_ENDIAN
         /* Directly access the little endian chars in the XDR buffer. */
         const char16_t* chars = nullptr;
         if (length) {
-            const uint8_t *ptr;
+            // In the |mode == XDR_ENCODE| case above, when |nchars > 0|,
+            // |XDRState::codeChars(char16_t*, size_t nchars)| will align the
+            // buffer.  This code never calls that function, but it must act
+            // *as if* it had, so we must align manually here.
+            MOZ_TRY(xdr->codeAlign(sizeof(char16_t)));
+
+            const uint8_t* ptr;
             size_t nbyte = length * sizeof(char16_t);
             MOZ_TRY(xdr->peekData(&ptr, nbyte));
             MOZ_ASSERT(reinterpret_cast<uintptr_t>(ptr) % sizeof(char16_t) == 0,
                        "non-aligned buffer during JSAtom decoding");
             chars = reinterpret_cast<const char16_t*>(ptr);
         }
         atom = AtomizeChars(cx, chars, length);
 #else
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -93,16 +93,20 @@ XDRState<mode>::codeChars(Utf8Unit* unit
 
 template<XDRMode mode>
 XDRResult
 XDRState<mode>::codeChars(char16_t* chars, size_t nchars)
 {
     if (nchars == 0) {
         return Ok();
     }
+
+    // Align the buffer to avoid unaligned loads.
+    MOZ_TRY(codeAlign(sizeof(char16_t)));
+
     size_t nbytes = nchars * sizeof(char16_t);
     if (mode == XDR_ENCODE) {
         uint8_t* ptr = buf.write(nbytes);
         if (!ptr) {
             return fail(JS::TranscodeResult_Throw);
         }
         mozilla::NativeEndian::copyAndSwapToLittleEndian(ptr, chars, nchars);
     } else {
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -487,16 +487,18 @@ class XDRState : public XDRCoderBase
             *sp = reinterpret_cast<const char*>(ptr);
         }
         return Ok();
     }
 
     XDRResult codeChars(JS::Latin1Char* chars, size_t nchars);
     XDRResult codeChars(mozilla::Utf8Unit* units, size_t nchars);
 
+    // If |nchars > 0|, this calls |codeAlign(sizeof(char16_t))| so callers
+    // don't have to.
     XDRResult codeChars(char16_t* chars, size_t nchars);
 
     XDRResult codeFunction(JS::MutableHandleFunction objp,
                            HandleScriptSourceObject sourceObject = nullptr);
     XDRResult codeScript(MutableHandleScript scriptp);
 };
 
 using XDREncoder = XDRState<XDR_ENCODE>;