From 23b74dcced648421d17b7a84faaa0101c82c3e81 Mon Sep 17 00:00:00 2001
From: murgatroid99 <mlumish@google.com>
Date: Mon, 31 Jul 2017 13:15:19 -0700
Subject: [PATCH] Node: fix segfault with incorrect status argument types

---
 src/node/ext/call.cc       | 10 ++++-
 src/node/test/call_test.js | 85 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/src/node/ext/call.cc b/src/node/ext/call.cc
index 71e6904008..26095a78f9 100644
--- a/src/node/ext/call.cc
+++ b/src/node/ext/call.cc
@@ -260,7 +260,10 @@ class SendClientCloseOp : public Op {
 
 class SendServerStatusOp : public Op {
  public:
-  SendServerStatusOp() { grpc_metadata_array_init(&status_metadata); }
+  SendServerStatusOp() {
+    details = grpc_empty_slice();
+    grpc_metadata_array_init(&status_metadata);
+  }
   ~SendServerStatusOp() {
     grpc_slice_unref(details);
     DestroyMetadataArray(&status_metadata);
@@ -381,7 +384,10 @@ class ReadMessageOp : public Op {
 
 class ClientStatusOp : public Op {
  public:
-  ClientStatusOp() { grpc_metadata_array_init(&metadata_array); }
+  ClientStatusOp() {
+    grpc_metadata_array_init(&metadata_array);
+    status_details = grpc_empty_slice();
+  }
 
   ~ClientStatusOp() {
     grpc_metadata_array_destroy(&metadata_array);
diff --git a/src/node/test/call_test.js b/src/node/test/call_test.js
index aebd298e32..e19f47beb9 100644
--- a/src/node/test/call_test.js
+++ b/src/node/test/call_test.js
@@ -188,6 +188,91 @@ describe('call', function() {
       }, TypeError);
     });
   });
+  describe('startBatch with message', function() {
+    it('should fail with non-buffer arguments', function() {
+      var call = new grpc.Call(channel, 'method', getDeadline(1));
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_MESSAGE] = null;
+        call.startBatch(batch, function(){});
+      }, TypeError);
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_MESSAGE] = 5;
+        call.startBatch(batch, function(){});
+      }, TypeError);
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_MESSAGE] = 'value';
+        call.startBatch(batch, function(){});
+      }, TypeError);
+    });
+  });
+  describe('startBatch with status', function() {
+    it('should fail without a code', function() {
+      var call = new grpc.Call(channel, 'method', getDeadline(1));
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+          details: 'details string',
+          metadata: {}
+        };
+        call.startBatch(batch, function(){});
+      }, TypeError);
+    });
+    it('should fail without details', function() {
+      var call = new grpc.Call(channel, 'method', getDeadline(1));
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+          code: 0,
+          metadata: {}
+        };
+        call.startBatch(batch, function(){});
+      }, TypeError);
+    });
+    it('should fail without metadata', function() {
+      var call = new grpc.Call(channel, 'method', getDeadline(1));
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+          code: 0,
+          details: 'details string'
+        };
+        call.startBatch(batch, function(){});
+      }, TypeError);
+    });
+    it('should fail with incorrectly typed arguments', function() {
+      var call = new grpc.Call(channel, 'method', getDeadline(1));
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+          code: 'code string',
+          details: 'details string',
+          metadata: {}
+        };
+        call.startBatch(batch, function(){});
+      }, TypeError);
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+          code: 0,
+          details: 5,
+          metadata: {}
+        };
+        call.startBatch(batch, function(){});
+      }, TypeError);
+      assert.throws(function() {
+        var batch = {};
+        batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+          code: 0,
+          details: 'details string',
+          metadata: 'abc'
+        };
+        call.startBatch(batch, function(){});
+      }, TypeError);
+    });
+  });
   describe('cancel', function() {
     it('should succeed', function() {
       var call = new grpc.Call(channel, 'method', getDeadline(1));
-- 
GitLab