[d8] bounds-check before getting Shell::Worker internal field
authorcaitpotter88 <caitpotter88@gmail.com>
Fri, 17 Jul 2015 21:44:26 +0000 (14:44 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 17 Jul 2015 21:44:37 +0000 (21:44 +0000)
Prevents fatal error in debug builds

BUG=v8:4271, 506954
R=binji@chromium.org
LOG=N

Committed: https://crrev.com/43ce9c6f101c4224addd9a54e0c39963188dc7fa
Cr-Commit-Position: refs/heads/master@{#29524}

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

Cr-Commit-Position: refs/heads/master@{#29737}

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

index 344325e..457b4c1 100644 (file)
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -720,14 +720,17 @@ void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
   Isolate* isolate = args.GetIsolate();
   HandleScope handle_scope(isolate);
   Local<Context> context = isolate->GetCurrentContext();
+  Local<Value> this_value;
 
   if (args.Length() < 1) {
     Throw(isolate, "Invalid argument");
     return;
   }
 
-  Local<Value> this_value = args.This()->GetInternalField(0);
-  if (!this_value->IsExternal()) {
+  if (args.This()->InternalFieldCount() > 0) {
+    this_value = args.This()->GetInternalField(0);
+  }
+  if (this_value.IsEmpty()) {
     Throw(isolate, "this is not a Worker");
     return;
   }
@@ -773,9 +776,11 @@ void Shell::WorkerPostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
 void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
   Isolate* isolate = args.GetIsolate();
   HandleScope handle_scope(isolate);
-
-  Local<Value> this_value = args.This()->GetInternalField(0);
-  if (!this_value->IsExternal()) {
+  Local<Value> this_value;
+  if (args.This()->InternalFieldCount() > 0) {
+    this_value = args.This()->GetInternalField(0);
+  }
+  if (this_value.IsEmpty()) {
     Throw(isolate, "this is not a Worker");
     return;
   }
@@ -798,8 +803,11 @@ void Shell::WorkerGetMessage(const v8::FunctionCallbackInfo<v8::Value>& args) {
 void Shell::WorkerTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) {
   Isolate* isolate = args.GetIsolate();
   HandleScope handle_scope(isolate);
-  Local<Value> this_value = args.This()->GetInternalField(0);
-  if (!this_value->IsExternal()) {
+  Local<Value> this_value;
+  if (args.This()->InternalFieldCount() > 0) {
+    this_value = args.This()->GetInternalField(0);
+  }
+  if (this_value.IsEmpty()) {
     Throw(isolate, "this is not a Worker");
     return;
   }
diff --git a/test/mjsunit/regress/regress-4271.js b/test/mjsunit/regress/regress-4271.js
new file mode 100644 (file)
index 0000000..bc18771
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+if (this.Worker) {
+  // Throw rather than overflow internal field index
+  assertThrows(function() {
+    Worker.prototype.terminate();
+  });
+
+  assertThrows(function() {
+    Worker.prototype.getMessage();
+  });
+
+  assertThrows(function() {
+    Worker.prototype.postMessage({});
+  });
+
+  // Don't throw for real worker
+  var worker = new Worker('');
+  worker.getMessage();
+  worker.postMessage({});
+  worker.terminate();
+}