Revision: 20222
Author:   [email protected]
Date:     Tue Mar 25 07:48:31 2014 UTC
Log:      Merged r20022 into 3.24 branch.

Apply numeric casts correctly in typed arrays and related code.

BUG=353004
LOG=N
[email protected]

Review URL: https://codereview.chromium.org/209393014
http://code.google.com/p/v8/source/detail?r=20222

Added:
 /branches/3.24/test/mjsunit/regress/regress-353004.js
Modified:
 /branches/3.24/src/api.cc
 /branches/3.24/src/arraybuffer.js
 /branches/3.24/src/runtime.cc
 /branches/3.24/src/runtime.h
 /branches/3.24/src/typedarray.js
 /branches/3.24/src/version.cc

=======================================
--- /dev/null
+++ /branches/3.24/test/mjsunit/regress/regress-353004.js Tue Mar 25 07:48:31 2014 UTC
@@ -0,0 +1,74 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+var buffer1 = new ArrayBuffer(100 * 1024);
+
+var array1 = new Uint8Array(buffer1, {valueOf : function() {
+  %ArrayBufferNeuter(buffer1);
+  return 0;
+}});
+
+assertEquals(0, array1.length);
+
+var buffer2 = new ArrayBuffer(100 * 1024);
+
+assertThrows(function() {
+  var array2 = new Uint8Array(buffer2, 0, {valueOf : function() {
+      %ArrayBufferNeuter(buffer2);
+      return 100 * 1024;
+  }});
+}, RangeError);
+
+
+var buffer3 = new ArrayBuffer(100 * 1024 * 1024);
+var dataView1 = new DataView(buffer3, {valueOf : function() {
+  %ArrayBufferNeuter(buffer3);
+  return 0;
+}});
+
+assertEquals(0, dataView1.byteLength);
+
+var buffer4 = new ArrayBuffer(100 * 1024);
+assertThrows(function() {
+  var dataView2 = new DataView(buffer4, 0, {valueOf : function() {
+    %ArrayBufferNeuter(buffer4);
+    return 100 * 1024 * 1024;
+  }});
+}, RangeError);
+
+
+var buffer5 = new ArrayBuffer(100 * 1024);
+var buffer6 = buffer5.slice({valueOf : function() {
+  %ArrayBufferNeuter(buffer5);
+  return 0;
+}}, 100 * 1024 * 1024);
+assertEquals(0, buffer6.byteLength);
+
+
+var buffer7 = new ArrayBuffer(100 * 1024 * 1024);
+var buffer8 = buffer7.slice(0, {valueOf : function() {
+  %ArrayBufferNeuter(buffer7);
+  return 100 * 1024 * 1024;
+}});
+assertEquals(0, buffer8.byteLength);
+
+var buffer9 = new ArrayBuffer(1024);
+var array9 = new Uint8Array(buffer9);
+var array10 = array9.subarray({valueOf : function() {
+    %ArrayBufferNeuter(buffer9);
+    return 0;
+  }}, 1024);
+assertEquals(0, array9.length);
+assertEquals(0, array10.length);
+
+var buffer11 = new ArrayBuffer(1024);
+var array11 = new Uint8Array(buffer11);
+var array12 = array11.subarray(0, {valueOf : function() {
+      %ArrayBufferNeuter(buffer11);
+      return 1024;
+    }});
+assertEquals(0, array11.length);
+assertEquals(0, array12.length);
=======================================
--- /branches/3.24/src/api.cc   Thu Feb  6 01:06:18 2014 UTC
+++ /branches/3.24/src/api.cc   Tue Mar 25 07:48:31 2014 UTC
@@ -5805,20 +5805,7 @@
                   "Only externalized ArrayBuffers can be neutered");
   LOG_API(obj->GetIsolate(), "v8::ArrayBuffer::Neuter()");
   ENTER_V8(isolate);
-
-  for (i::Handle<i::Object> view_obj(obj->weak_first_view(), isolate);
-       !view_obj->IsUndefined();) {
- i::Handle<i::JSArrayBufferView> view(i::JSArrayBufferView::cast(*view_obj));
-    if (view->IsJSTypedArray()) {
-      i::JSTypedArray::cast(*view)->Neuter();
-    } else if (view->IsJSDataView()) {
-      i::JSDataView::cast(*view)->Neuter();
-    } else {
-      UNREACHABLE();
-    }
-    view_obj = i::handle(view->weak_next(), isolate);
-  }
-  obj->Neuter();
+  i::Runtime::NeuterArrayBuffer(obj);
 }


=======================================
--- /branches/3.24/src/arraybuffer.js   Wed Mar 12 19:28:35 2014 UTC
+++ /branches/3.24/src/arraybuffer.js   Tue Mar 25 07:48:31 2014 UTC
@@ -56,6 +56,9 @@
   }

   var relativeStart = TO_INTEGER(start);
+  if (!IS_UNDEFINED(end)) {
+    end = TO_INTEGER(end);
+  }
   var first;
   var byte_length = %ArrayBufferGetByteLength(this);
   if (relativeStart < 0) {
@@ -63,7 +66,7 @@
   } else {
     first = MathMin(relativeStart, byte_length);
   }
-  var relativeEnd = IS_UNDEFINED(end) ? byte_length : TO_INTEGER(end);
+  var relativeEnd = IS_UNDEFINED(end) ? byte_length : end;
   var fin;
   if (relativeEnd < 0) {
     fin = MathMax(byte_length + relativeEnd, 0);
=======================================
--- /branches/3.24/src/runtime.cc       Wed Mar 12 19:28:35 2014 UTC
+++ /branches/3.24/src/runtime.cc       Tue Mar 25 07:48:31 2014 UTC
@@ -794,6 +794,24 @@

   return true;
 }
+
+
+void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
+  Isolate* isolate = array_buffer->GetIsolate();
+  for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate);
+       !view_obj->IsUndefined();) {
+    Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj));
+    if (view->IsJSTypedArray()) {
+      JSTypedArray::cast(*view)->Neuter();
+    } else if (view->IsJSDataView()) {
+      JSDataView::cast(*view)->Neuter();
+    } else {
+      UNREACHABLE();
+    }
+    view_obj = handle(view->weak_next(), isolate);
+  }
+  array_buffer->Neuter();
+}


 RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferInitialize) {
@@ -849,7 +867,9 @@

   if (target_length == 0) return isolate->heap()->undefined_value();

- ASSERT(NumberToSize(isolate, source->byte_length()) - target_length >= start);
+  size_t source_byte_length = NumberToSize(isolate, source->byte_length());
+  CHECK(start <= source_byte_length);
+  CHECK(source_byte_length - start >= target_length);
uint8_t* source_data = reinterpret_cast<uint8_t*>(source->backing_store()); uint8_t* target_data = reinterpret_cast<uint8_t*>(target->backing_store());
   CopyBytes(target_data, source_data + start, target_length);
@@ -865,6 +885,19 @@
     ? isolate->heap()->true_value()
     : isolate->heap()->false_value();
 }
+
+
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayBufferNeuter) {
+  HandleScope scope(isolate);
+  CONVERT_ARG_HANDLE_CHECKED(JSArrayBuffer, array_buffer, 0);
+  ASSERT(!array_buffer->is_external());
+  void* backing_store = array_buffer->backing_store();
+  size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
+  array_buffer->set_is_external(true);
+  Runtime::NeuterArrayBuffer(array_buffer);
+  V8::ArrayBufferAllocator()->Free(backing_store, byte_length);
+  return isolate->heap()->undefined_value();
+}


 void Runtime::ArrayIdToTypeAndSize(
@@ -910,7 +943,12 @@

   size_t byte_offset = NumberToSize(isolate, *byte_offset_object);
   size_t byte_length = NumberToSize(isolate, *byte_length_object);
-  ASSERT(byte_length % element_size == 0);
+  size_t array_buffer_byte_length =
+      NumberToSize(isolate, buffer->byte_length());
+  CHECK(byte_offset <= array_buffer_byte_length);
+  CHECK(array_buffer_byte_length - byte_offset >= byte_length);
+
+  CHECK_EQ(0, static_cast<int>(byte_length % element_size));
   size_t length = byte_length / element_size;

   if (length > static_cast<unsigned>(Smi::kMaxValue)) {
=======================================
--- /branches/3.24/src/runtime.h        Fri Feb  7 09:11:16 2014 UTC
+++ /branches/3.24/src/runtime.h        Tue Mar 25 07:48:31 2014 UTC
@@ -365,6 +365,7 @@
   F(ArrayBufferGetByteLength, 1, 1)\
   F(ArrayBufferSliceImpl, 3, 1) \
   F(ArrayBufferIsView, 1, 1) \
+  F(ArrayBufferNeuter, 1, 1) \
   \
   F(TypedArrayInitialize, 5, 1) \
   F(TypedArrayInitializeFromArrayLike, 4, 1) \
@@ -827,6 +828,8 @@
       size_t allocated_length,
       bool initialize = true);

+  static void NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer);
+
   static void FreeArrayBuffer(
       Isolate* isolate,
       JSArrayBuffer* phantom_array_buffer);
=======================================
--- /branches/3.24/src/typedarray.js    Wed Mar 12 19:28:35 2014 UTC
+++ /branches/3.24/src/typedarray.js    Tue Mar 25 07:48:31 2014 UTC
@@ -49,12 +49,20 @@

 macro TYPED_ARRAY_CONSTRUCTOR(ARRAY_ID, NAME, ELEMENT_SIZE)
   function NAMEConstructByArrayBuffer(obj, buffer, byteOffset, length) {
+    if (!IS_UNDEFINED(byteOffset)) {
+        byteOffset =
+            ToPositiveInteger(byteOffset,  "invalid_typed_array_length");
+    }
+    if (!IS_UNDEFINED(length)) {
+        length = ToPositiveInteger(length, "invalid_typed_array_length");
+    }
+
     var bufferByteLength = %ArrayBufferGetByteLength(buffer);
     var offset;
     if (IS_UNDEFINED(byteOffset)) {
       offset = 0;
     } else {
-      offset = ToPositiveInteger(byteOffset, "invalid_typed_array_length");
+      offset = byteOffset;

       if (offset % ELEMENT_SIZE !== 0) {
         throw MakeRangeError("invalid_typed_array_alignment",
@@ -75,7 +83,7 @@
       newByteLength = bufferByteLength - offset;
       newLength = newByteLength / ELEMENT_SIZE;
     } else {
- var newLength = ToPositiveInteger(length, "invalid_typed_array_length");
+      var newLength = length;
       newByteLength = newLength * ELEMENT_SIZE;
     }
     if ((offset + newByteLength > bufferByteLength)
@@ -99,6 +107,7 @@
   function NAMEConstructByArrayLike(obj, arrayLike) {
     var length = arrayLike.length;
     var l = ToPositiveInteger(length, "invalid_typed_array_length");
+
     if (l > %MaxSmi()) {
       throw MakeRangeError("invalid_typed_array_length");
     }
@@ -148,15 +157,19 @@

 function CreateSubArray(elementSize, constructor) {
   return function(begin, end) {
+    var beginInt = TO_INTEGER(begin);
+    if (!IS_UNDEFINED(end)) {
+      end = TO_INTEGER(end);
+    }
+
     var srcLength = %TypedArrayGetLength(this);
-    var beginInt = TO_INTEGER(begin);
     if (beginInt < 0) {
       beginInt = MathMax(0, srcLength + beginInt);
     } else {
       beginInt = MathMin(srcLength, beginInt);
     }

-    var endInt = IS_UNDEFINED(end) ? srcLength : TO_INTEGER(end);
+    var endInt = IS_UNDEFINED(end) ? srcLength : end;
     if (endInt < 0) {
       endInt = MathMax(0, srcLength + endInt);
     } else {
@@ -317,14 +330,23 @@
     if (!IS_ARRAYBUFFER(buffer)) {
       throw MakeTypeError('data_view_not_array_buffer', []);
     }
+    if (!IS_UNDEFINED(byteOffset)) {
+ byteOffset = ToPositiveInteger(byteOffset, 'invalid_data_view_offset');
+    }
+    if (!IS_UNDEFINED(byteLength)) {
+        byteLength = TO_INTEGER(byteLength);
+    }
+
     var bufferByteLength = %ArrayBufferGetByteLength(buffer);
-    var offset = IS_UNDEFINED(byteOffset) ?
-      0 : ToPositiveInteger(byteOffset, 'invalid_data_view_offset');
+
+    var offset = IS_UNDEFINED(byteOffset) ?  0 : byteOffset;
     if (offset > bufferByteLength) {
       throw MakeRangeError('invalid_data_view_offset');
     }
-    var length = IS_UNDEFINED(byteLength) ?
-      bufferByteLength - offset : TO_INTEGER(byteLength);
+
+    var length = IS_UNDEFINED(byteLength)
+        ? bufferByteLength - offset
+        : byteLength;
     if (length < 0 || offset + length > bufferByteLength) {
       throw new MakeRangeError('invalid_data_view_length');
     }
=======================================
--- /branches/3.24/src/version.cc       Wed Mar 19 12:50:00 2014 UTC
+++ /branches/3.24/src/version.cc       Tue Mar 25 07:48:31 2014 UTC
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     24
 #define BUILD_NUMBER      35
-#define PATCH_LEVEL       18
+#define PATCH_LEVEL       19
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to