THRIFT-3062 fix segfault on invalid port number

This closes #425

commit 9d5654389daab6ab6be6bdae110a1acede51e945
Author: Jim King <jim.king@simplivity.com>
Date: 2015-04-04T19:47:34Z
diff --git a/lib/cpp/src/thrift/transport/TServerSocket.cpp b/lib/cpp/src/thrift/transport/TServerSocket.cpp
index fccbcfa..cb4d1fc 100644
--- a/lib/cpp/src/thrift/transport/TServerSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TServerSocket.cpp
@@ -192,9 +192,14 @@
     intSock2_ = sv[0];
   }
 
+  // Validate port number
+  if (port_ < 0 || port_ > 0xFFFF) {
+    throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid");
+  }
+
   struct addrinfo hints, *res, *res0;
   int error;
-  char port[sizeof("65536") + 1];
+  char port[sizeof("65535")];
   std::memset(&hints, 0, sizeof(hints));
   hints.ai_family = PF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
diff --git a/lib/cpp/src/thrift/transport/TSocket.cpp b/lib/cpp/src/thrift/transport/TSocket.cpp
index 3295073..bcea291 100644
--- a/lib/cpp/src/thrift/transport/TSocket.cpp
+++ b/lib/cpp/src/thrift/transport/TSocket.cpp
@@ -358,7 +358,7 @@
 
   // Validate port number
   if (port_ < 0 || port_ > 0xFFFF) {
-    throw TTransportException(TTransportException::NOT_OPEN, "Specified port is invalid");
+    throw TTransportException(TTransportException::BAD_ARGS, "Specified port is invalid");
   }
 
   struct addrinfo hints, *res, *res0;
diff --git a/lib/cpp/test/TServerSocketTest.cpp b/lib/cpp/test/TServerSocketTest.cpp
index ebfd03f..eee7c26 100644
--- a/lib/cpp/test/TServerSocketTest.cpp
+++ b/lib/cpp/test/TServerSocketTest.cpp
@@ -21,6 +21,7 @@
 #include <thrift/transport/TSocket.h>
 #include <thrift/transport/TServerSocket.h>
 #include "TestPortFixture.h"
+#include "TTransportCheckThrow.h"
 
 using apache::thrift::transport::TServerSocket;
 using apache::thrift::transport::TSocket;
@@ -51,6 +52,15 @@
     sock2.close();
 }
 
+BOOST_AUTO_TEST_CASE( test_listen_valid_port )
+{
+    TServerSocket sock1(-1);
+    TTRANSPORT_CHECK_THROW(sock1.listen(), TTransportException::BAD_ARGS);
+
+    TServerSocket sock2(65536);
+    TTRANSPORT_CHECK_THROW(sock2.listen(), TTransportException::BAD_ARGS);
+}
+
 BOOST_AUTO_TEST_CASE( test_close_before_listen )
 {
     TServerSocket sock1("localhost", m_serverPort);
diff --git a/lib/cpp/test/TTransportCheckThrow.h b/lib/cpp/test/TTransportCheckThrow.h
new file mode 100644
index 0000000..3b212e1
--- /dev/null
+++ b/lib/cpp/test/TTransportCheckThrow.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#pragma once
+
+#define TTRANSPORT_CHECK_THROW(_CALL, _TYPE) \
+  { bool caught = false; \
+    try { (_CALL); } \
+    catch (TTransportException& ex) { BOOST_CHECK_EQUAL(ex.getType(), _TYPE); caught = true; } \
+    BOOST_CHECK_MESSAGE(caught, "expected TTransportException but nothing was thrown"); }
+
+#define TTRANSPORT_REQUIRE_THROW(_CALL, _TYPE) \
+  { bool caught = false; \
+    try { (_CALL); } \
+    catch (TTransportException& ex) { BOOST_REQUIRE_EQUAL(ex.getType(), _TYPE); caught = true; } \
+    BOOST_REQUIRE_MESSAGE(caught, "expected TTransportException but nothing was thrown"); }
+