Bug 1530296 - Be more careful about converting int32_t to DataView element type. r=froydnj
authorJeff Walden <jwalden@mit.edu>
Mon, 25 Feb 2019 12:46:01 -0800
changeset 461648 5ea654f841a45073afaf4df9ec4829932ef6c399
parent 461647 18e52bd7c3adaa0e9bfae00942c935cb7568c054
child 461649 7af55c5b089d26a3cfe5ef38a5948410aeed6805
push id35626
push usercsabou@mozilla.com
push dateThu, 28 Feb 2019 11:31:08 +0000
treeherdermozilla-central@2ea0c1db7e60 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1530296
milestone67.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 1530296 - Be more careful about converting int32_t to DataView element type. r=froydnj
js/src/builtin/DataViewObject.cpp
--- a/js/src/builtin/DataViewObject.cpp
+++ b/js/src/builtin/DataViewObject.cpp
@@ -4,18 +4,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "builtin/DataViewObject.h"
 
 #include "mozilla/Alignment.h"
 #include "mozilla/Casting.h"
 #include "mozilla/EndianUtils.h"
+#include "mozilla/WrappingOperations.h"
 
 #include <string.h>
+#include <type_traits>
 
 #include "jsapi.h"
 #include "jsnum.h"
 
 #include "builtin/Array.h"
 #include "jit/AtomicOperations.h"
 #include "js/Conversions.h"
 #include "js/PropertySpec.h"
@@ -34,16 +36,17 @@
 #include "vm/ArrayBufferObject-inl.h"
 #include "vm/NativeObject-inl.h"
 
 using namespace js;
 
 using JS::CanonicalizeNaN;
 using JS::ToInt32;
 using mozilla::AssertedCast;
+using mozilla::WrapToSigned;
 
 DataViewObject* DataViewObject::create(
     JSContext* cx, uint32_t byteOffset, uint32_t byteLength,
     Handle<ArrayBufferObjectMaybeShared*> arrayBuffer, HandleObject proto) {
   if (arrayBuffer->isDetached()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_TYPED_ARRAY_DETACHED);
     return nullptr;
@@ -407,27 +410,34 @@ template <typename NativeType>
         val, data, needToSwapBytes(isLittleEndian));
   } else {
     DataViewIO<NativeType, uint8_t*>::fromBuffer(
         val, data.unwrapUnshared(), needToSwapBytes(isLittleEndian));
   }
   return true;
 }
 
+template <typename T>
+static inline T WrappingConvert(int32_t value) {
+  if (std::is_unsigned<T>::value) {
+    return static_cast<T>(value);
+  }
+
+  return WrapToSigned(static_cast<typename std::make_unsigned<T>::type>(value));
+}
+
 template <typename NativeType>
 static inline bool WebIDLCast(JSContext* cx, HandleValue value,
                               NativeType* out) {
-  int32_t temp;
-  if (!ToInt32(cx, value, &temp)) {
+  int32_t i;
+  if (!ToInt32(cx, value, &i)) {
     return false;
   }
-  // Technically, the behavior of assigning an out of range value to a signed
-  // variable is undefined. In practice, compilers seem to do what we want
-  // without issuing any warnings.
-  *out = static_cast<NativeType>(temp);
+
+  *out = WrappingConvert<NativeType>(i);
   return true;
 }
 
 template <>
 inline bool WebIDLCast<int64_t>(JSContext* cx, HandleValue value,
                                 int64_t* out) {
   RootedBigInt bi(cx, ToBigInt(cx, value));
   if (!bi) {