negative bounds checking on realm calls
authordcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 25 Feb 2014 09:15:05 +0000 (09:15 +0000)
committerdcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 25 Feb 2014 09:15:05 +0000 (09:15 +0000)
R=rossberg@chromium.org

LOG=N

BUG=344285

Review URL: https://codereview.chromium.org/169393002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19533 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/d8.cc
test/mjsunit/regress/regress-cr-344285.js [new file with mode: 0644]

index 76ff4f9..564aafe 100644 (file)
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -119,6 +119,8 @@ class PerIsolateData {
   Persistent<Context>* realms_;
   Persistent<Value> realm_shared_;
 
+  int RealmIndexOrThrow(const v8::FunctionCallbackInfo<v8::Value>& args,
+                        int arg_offset);
   int RealmFind(Handle<Context> context);
 };
 
@@ -288,6 +290,24 @@ int PerIsolateData::RealmFind(Handle<Context> context) {
 }
 
 
+int PerIsolateData::RealmIndexOrThrow(
+    const v8::FunctionCallbackInfo<v8::Value>& args,
+    int arg_offset) {
+  if (args.Length() < arg_offset || !args[arg_offset]->IsNumber()) {
+    Throw(args.GetIsolate(), "Invalid argument");
+    return -1;
+  }
+  int index = args[arg_offset]->Int32Value();
+  if (index < 0 ||
+      index >= realm_count_ ||
+      realms_[index].IsEmpty()) {
+    Throw(args.GetIsolate(), "Invalid realm index");
+    return -1;
+  }
+  return index;
+}
+
+
 #ifndef V8_SHARED
 // performance.now() returns a time stamp as double, measured in milliseconds.
 void Shell::PerformanceNow(const v8::FunctionCallbackInfo<v8::Value>& args) {
@@ -325,15 +345,8 @@ void Shell::RealmOwner(const v8::FunctionCallbackInfo<v8::Value>& args) {
 // (Note that properties of global objects cannot be read/written cross-realm.)
 void Shell::RealmGlobal(const v8::FunctionCallbackInfo<v8::Value>& args) {
   PerIsolateData* data = PerIsolateData::Get(args.GetIsolate());
-  if (args.Length() < 1 || !args[0]->IsNumber()) {
-    Throw(args.GetIsolate(), "Invalid argument");
-    return;
-  }
-  int index = args[0]->Uint32Value();
-  if (index >= data->realm_count_ || data->realms_[index].IsEmpty()) {
-    Throw(args.GetIsolate(), "Invalid realm index");
-    return;
-  }
+  int index = data->RealmIndexOrThrow(args, 0);
+  if (index == -1) return;
   args.GetReturnValue().Set(
       Local<Context>::New(args.GetIsolate(), data->realms_[index])->Global());
 }
@@ -361,13 +374,9 @@ void Shell::RealmCreate(const v8::FunctionCallbackInfo<v8::Value>& args) {
 void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
   Isolate* isolate = args.GetIsolate();
   PerIsolateData* data = PerIsolateData::Get(isolate);
-  if (args.Length() < 1 || !args[0]->IsNumber()) {
-    Throw(args.GetIsolate(), "Invalid argument");
-    return;
-  }
-  int index = args[0]->Uint32Value();
-  if (index >= data->realm_count_ || data->realms_[index].IsEmpty() ||
-      index == 0 ||
+  int index = data->RealmIndexOrThrow(args, 0);
+  if (index == -1) return;
+  if (index == 0 ||
       index == data->realm_current_ || index == data->realm_switch_) {
     Throw(args.GetIsolate(), "Invalid realm index");
     return;
@@ -380,15 +389,8 @@ void Shell::RealmDispose(const v8::FunctionCallbackInfo<v8::Value>& args) {
 void Shell::RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) {
   Isolate* isolate = args.GetIsolate();
   PerIsolateData* data = PerIsolateData::Get(isolate);
-  if (args.Length() < 1 || !args[0]->IsNumber()) {
-    Throw(args.GetIsolate(), "Invalid argument");
-    return;
-  }
-  int index = args[0]->Uint32Value();
-  if (index >= data->realm_count_ || data->realms_[index].IsEmpty()) {
-    Throw(args.GetIsolate(), "Invalid realm index");
-    return;
-  }
+  int index = data->RealmIndexOrThrow(args, 0);
+  if (index == -1) return;
   data->realm_switch_ = index;
 }
 
@@ -397,15 +399,12 @@ void Shell::RealmSwitch(const v8::FunctionCallbackInfo<v8::Value>& args) {
 void Shell::RealmEval(const v8::FunctionCallbackInfo<v8::Value>& args) {
   Isolate* isolate = args.GetIsolate();
   PerIsolateData* data = PerIsolateData::Get(isolate);
-  if (args.Length() < 2 || !args[0]->IsNumber() || !args[1]->IsString()) {
+  int index = data->RealmIndexOrThrow(args, 0);
+  if (index == -1) return;
+  if (args.Length() < 2 || !args[1]->IsString()) {
     Throw(args.GetIsolate(), "Invalid argument");
     return;
   }
-  int index = args[0]->Uint32Value();
-  if (index >= data->realm_count_ || data->realms_[index].IsEmpty()) {
-    Throw(args.GetIsolate(), "Invalid realm index");
-    return;
-  }
   Handle<Script> script = Script::New(args[1]->ToString());
   if (script.IsEmpty()) return;
   Local<Context> realm = Local<Context>::New(isolate, data->realms_[index]);
diff --git a/test/mjsunit/regress/regress-cr-344285.js b/test/mjsunit/regress/regress-cr-344285.js
new file mode 100644 (file)
index 0000000..42e8bd1
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+function __f_1(g) { return (g/-1) ^ 1; }
+var __v_0 = 1 << 31;
+var __v_2 = __f_1(__v_0);
+caught = false;
+try {
+  Realm.eval(__v_2, "Realm.global(0).y = 1");
+} catch (e) {
+  caught = true;
+}
+assertTrue(caught, "exception not caught");