Tidy up handshaker tester.

Do a better job with scopers for fds and posix_spawn_file_actions_t.
There's also no need to make a copy of handshaker_path with strdup.
The non-const parameter are because posix_spawn inherits execve's
C problem: unlike C++, C cannot cast from char *const * to
const char *const *, so POSIX APIs are not const-correct.

Finally, we freely use std::vector and friends in tests, so we don't
actually need to depend on bssl::Array.

Change-Id: I739dcb6b1a2d415d47ff9b2399eebec987aab0bc
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/46524
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/fuzzer.h b/ssl/test/fuzzer.h
index f10c4a0..eacbdc0 100644
--- a/ssl/test/fuzzer.h
+++ b/ssl/test/fuzzer.h
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include <algorithm>
+#include <vector>
 
 #include <openssl/bio.h>
 #include <openssl/bytestring.h>
@@ -30,7 +31,7 @@
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
 
-#include "../internal.h"
+#include "../../crypto/internal.h"
 #include "./fuzzer_tags.h"
 
 namespace {
@@ -324,7 +325,7 @@
         MoveBIOs(ssl_handoff.get(), ssl.get());
         // Ordinarily we would call SSL_serialize_handoff(ssl.get().  But for
         // fuzzing, use the serialized handoff that's getting fuzzed.
-        if (!SSL_apply_handoff(ssl_handoff.get(), handoff_)) {
+        if (!bssl::SSL_apply_handoff(ssl_handoff.get(), handoff_)) {
           if (debug_) {
             fprintf(stderr, "Handoff failed.\n");
           }
@@ -334,7 +335,7 @@
       } else if (ret < 0 &&
                  SSL_get_error(ssl_handshake, ret) == SSL_ERROR_HANDBACK) {
         MoveBIOs(ssl_handback.get(), ssl_handoff.get());
-        if (!SSL_apply_handback(ssl_handback.get(), handback_)) {
+        if (!bssl::SSL_apply_handback(ssl_handback.get(), handback_)) {
           if (debug_) {
             fprintf(stderr, "Handback failed.\n");
           }
@@ -497,7 +498,8 @@
           if (!CBS_get_u24_length_prefixed(cbs, &handoff)) {
             return nullptr;
           }
-          handoff_.CopyFrom(handoff);
+          handoff_.assign(CBS_data(&handoff),
+                          CBS_data(&handoff) + CBS_len(&handoff));
           bssl::SSL_set_handoff_mode(ssl.get(), 1);
           break;
         }
@@ -507,7 +509,8 @@
           if (!CBS_get_u24_length_prefixed(cbs, &handback)) {
             return nullptr;
           }
-          handback_.CopyFrom(handback);
+          handback_.assign(CBS_data(&handback),
+                           CBS_data(&handback) + CBS_len(&handback));
           bssl::SSL_set_handoff_mode(ssl.get(), 1);
           break;
         }
@@ -567,7 +570,7 @@
   Protocol protocol_;
   Role role_;
   bssl::UniquePtr<SSL_CTX> ctx_;
-  bssl::Array<uint8_t> handoff_, handback_;
+  std::vector<uint8_t> handoff_, handback_;
 };
 
 const BIO_METHOD TLSFuzzer::kBIOMethod = {
diff --git a/ssl/test/handshake_util.cc b/ssl/test/handshake_util.cc
index aca2556..a94fbaf 100644
--- a/ssl/test/handshake_util.cc
+++ b/ssl/test/handshake_util.cc
@@ -27,6 +27,7 @@
 #endif
 
 #include <functional>
+#include <vector>
 
 #include "async_bio.h"
 #include "packeted_bio.h"
@@ -304,16 +305,38 @@
 class ScopedFD {
  public:
   explicit ScopedFD(int fd): fd_(fd) {}
-  ~ScopedFD() { close(fd_); }
+  ~ScopedFD() { Close(); }
+  ScopedFD(const ScopedFD &) = delete;
+  ScopedFD &operator=(const ScopedFD &) = delete;
+
+  void Close() {
+    if (fd_ >= 0) {
+      close(fd_);
+    }
+    fd_ = -1;
+  }
+
  private:
-  const int fd_;
+  int fd_;
+};
+
+class FileActionsDestroyer {
+ public:
+  explicit FileActionsDestroyer(posix_spawn_file_actions_t *actions)
+      : actions_(actions) {}
+  ~FileActionsDestroyer() { posix_spawn_file_actions_destroy(actions_); }
+  FileActionsDestroyer(const FileActionsDestroyer &) = delete;
+  FileActionsDestroyer &operator=(const FileActionsDestroyer &) = delete;
+
+ private:
+  posix_spawn_file_actions_t *actions_;
 };
 
 // RunHandshaker forks and execs the handshaker binary, handing off |input|,
 // and, after proxying some amount of handshake traffic, handing back |out|.
 static bool RunHandshaker(BIO *bio, const TestConfig *config, bool is_resume,
-                          const Array<uint8_t> &input,
-                          Array<uint8_t> *out) {
+                          Span<const uint8_t> input,
+                          std::vector<uint8_t> *out) {
   if (config->handshaker_path.empty()) {
     fprintf(stderr, "no -handshaker-path specified\n");
     return false;
@@ -330,6 +353,8 @@
     perror("socketpair");
     return false;
   }
+  ScopedFD control0_closer(control[0]), control1_closer(control[1]);
+
   int rfd[2], wfd[2];
   // We use pipes, rather than some other mechanism, for their buffers.  During
   // the handshake, this process acts as a dumb proxy until receiving the
@@ -341,21 +366,26 @@
   // handshaker has not explicitly requested as a result of hitting
   // |SSL_ERROR_WANT_READ|.  Pipes allow the data to sit in a buffer while the
   // two processes synchronize over the |control| channel.
-  if (pipe(rfd) != 0 || pipe(wfd) != 0) {
-    perror("pipe2");
+  if (pipe(rfd) != 0) {
+    perror("pipe");
     return false;
   }
+  ScopedFD rfd0_closer(rfd[0]), rfd1_closer(rfd[1]);
+
+  if (pipe(wfd) != 0) {
+    perror("pipe");
+    return false;
+  }
+  ScopedFD wfd0_closer(wfd[0]), wfd1_closer(wfd[1]);
 
   fflush(stdout);
   fflush(stderr);
 
-  std::vector<char *> args;
-  bssl::UniquePtr<char> handshaker_path(
-      OPENSSL_strdup(config->handshaker_path.c_str()));
-  args.push_back(handshaker_path.get());
-  char resume[] = "-handshaker-resume";
+  std::vector<const char *> args;
+  args.push_back(config->handshaker_path.c_str());
+  static const char kResumeFlag[] = "-handshaker-resume";
   if (is_resume) {
-    args.push_back(resume);
+    args.push_back(kResumeFlag);
   }
   // config->argv omits argv[0].
   for (int j = 0; j < config->argc; ++j) {
@@ -364,10 +394,13 @@
   args.push_back(nullptr);
 
   posix_spawn_file_actions_t actions;
-  if (posix_spawn_file_actions_init(&actions) != 0 ||
-      posix_spawn_file_actions_addclose(&actions, control[0]) ||
-      posix_spawn_file_actions_addclose(&actions, rfd[1]) ||
-      posix_spawn_file_actions_addclose(&actions, wfd[0])) {
+  if (posix_spawn_file_actions_init(&actions) != 0) {
+    return false;
+  }
+  FileActionsDestroyer actions_destroyer(&actions);
+  if (posix_spawn_file_actions_addclose(&actions, control[0]) != 0 ||
+      posix_spawn_file_actions_addclose(&actions, rfd[1]) != 0 ||
+      posix_spawn_file_actions_addclose(&actions, wfd[0]) != 0) {
     return false;
   }
   assert(kFdControl != rfd[0]);
@@ -391,19 +424,14 @@
   // MSan doesn't know that |posix_spawn| initializes its output, so initialize
   // it to -1.
   pid_t handshaker_pid = -1;
-  int ret = posix_spawn(&handshaker_pid, args[0], &actions, nullptr,
-                        args.data(), environ);
-  if (posix_spawn_file_actions_destroy(&actions) != 0 ||
-      ret != 0) {
+  if (posix_spawn(&handshaker_pid, args[0], &actions, nullptr,
+                  const_cast<char *const *>(args.data()), environ) != 0) {
     return false;
   }
 
-  close(control[1]);
-  close(rfd[0]);
-  close(wfd[1]);
-  ScopedFD rfd_closer(rfd[1]);
-  ScopedFD wfd_closer(wfd[0]);
-  ScopedFD control_closer(control[0]);
+  control1_closer.Close();
+  rfd0_closer.Close();
+  wfd1_closer.Close();
 
   if (write_eintr(control[0], input.data(), input.size()) == -1) {
     perror("write");
@@ -424,13 +452,14 @@
   }
 
   constexpr size_t kBufSize = 1024 * 1024;
-  bssl::UniquePtr<uint8_t> buf((uint8_t *) OPENSSL_malloc(kBufSize));
-  int len = read_eintr(control[0], buf.get(), kBufSize);
+  std::vector<uint8_t> buf(kBufSize);
+  ssize_t len = read_eintr(control[0], buf.data(), buf.size());
   if (len == -1) {
     perror("read");
     return false;
   }
-  out->CopyFrom({buf.get(), (size_t)len});
+  buf.resize(len);
+  *out = std::move(buf);
   return true;
 }
 
@@ -438,7 +467,7 @@
 // be passed to the handshaker.  The serialized state includes both the SSL
 // handoff, as well test-related state.
 static bool PrepareHandoff(SSL *ssl, SettingsWriter *writer,
-                           Array<uint8_t> *out_handoff) {
+                           std::vector<uint8_t> *out_handoff) {
   SSL_set_handoff_mode(ssl, 1);
 
   const TestConfig *config = GetTestConfig(ssl);
@@ -460,12 +489,14 @@
   if (!CBB_init(cbb.get(), 512) ||
       !SSL_serialize_handoff(ssl, cbb.get(), &hello) ||
       !writer->WriteHandoff({CBB_data(cbb.get()), CBB_len(cbb.get())}) ||
-      !SerializeContextState(ssl->ctx.get(), cbb.get()) ||
+      !SerializeContextState(SSL_get_SSL_CTX(ssl), cbb.get()) ||
       !GetTestState(ssl)->Serialize(cbb.get())) {
     fprintf(stderr, "Handoff serialisation failed.\n");
     return false;
   }
-  return CBBFinishArray(cbb.get(), out_handoff);
+  out_handoff->assign(CBB_data(cbb.get()),
+                      CBB_data(cbb.get()) + CBB_len(cbb.get()));
+  return true;
 }
 
 // DoSplitHandshake delegates the SSL handshake to a separate process, called
@@ -476,11 +507,11 @@
 bool DoSplitHandshake(UniquePtr<SSL> *ssl, SettingsWriter *writer,
                       bool is_resume) {
   assert(SSL_get_rbio(ssl->get()) == SSL_get_wbio(ssl->get()));
-  Array<uint8_t> handshaker_input;
+  std::vector<uint8_t> handshaker_input;
   const TestConfig *config = GetTestConfig(ssl->get());
   // out is the response from the handshaker, which includes a serialized
   // handback message, but also serialized updates to the |TestState|.
-  Array<uint8_t> out;
+  std::vector<uint8_t> out;
   if (!PrepareHandoff(ssl->get(), writer, &handshaker_input) ||
       !RunHandshaker(SSL_get_rbio(ssl->get()), config, is_resume,
                      handshaker_input, &out)) {
@@ -488,19 +519,17 @@
     return false;
   }
 
-  UniquePtr<SSL> ssl_handback =
-      config->NewSSL((*ssl)->ctx.get(), nullptr, nullptr);
+  SSL_CTX *ctx = SSL_get_SSL_CTX(ssl->get());
+  UniquePtr<SSL> ssl_handback = config->NewSSL(ctx, nullptr, nullptr);
   if (!ssl_handback) {
     return false;
   }
   CBS output, handback;
   CBS_init(&output, out.data(), out.size());
   if (!CBS_get_u24_length_prefixed(&output, &handback) ||
-      !DeserializeContextState(&output, ssl_handback->ctx.get()) ||
-      !SetTestState(ssl_handback.get(), TestState::Deserialize(
-          &output, ssl_handback->ctx.get())) ||
-      !GetTestState(ssl_handback.get()) ||
-      !writer->WriteHandback(handback) ||
+      !DeserializeContextState(&output, ctx) ||
+      !SetTestState(ssl_handback.get(), TestState::Deserialize(&output, ctx)) ||
+      !GetTestState(ssl_handback.get()) || !writer->WriteHandback(handback) ||
       !SSL_apply_handback(ssl_handback.get(), handback)) {
     fprintf(stderr, "Handback failed.\n");
     return false;
diff --git a/ssl/test/handshaker.cc b/ssl/test/handshaker.cc
index 3a0ee57..74e39f3 100644
--- a/ssl/test/handshaker.cc
+++ b/ssl/test/handshaker.cc
@@ -21,7 +21,6 @@
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
 
-#include "../internal.h"
 #include "handshake_util.h"
 #include "test_config.h"
 #include "test_state.h"
@@ -91,20 +90,18 @@
 
   ScopedCBB output;
   CBB handback;
-  Array<uint8_t> bytes;
   if (!CBB_init(output.get(), 1024) ||
       !CBB_add_u24_length_prefixed(output.get(), &handback) ||
       !SSL_serialize_handback(ssl.get(), &handback) ||
-      !SerializeContextState(ssl->ctx.get(), output.get()) ||
-      !GetTestState(ssl.get())->Serialize(output.get()) ||
-      !CBBFinishArray(output.get(), &bytes)) {
+      !SerializeContextState(ctx.get(), output.get()) ||
+      !GetTestState(ssl.get())->Serialize(output.get())) {
     fprintf(stderr, "Handback serialisation failed.\n");
     return false;
   }
 
   char msg = kControlMsgHandback;
   if (write(control, &msg, 1) == -1 ||
-      write(control, bytes.data(), bytes.size()) == -1) {
+      write(control, CBB_data(output.get()), CBB_len(output.get())) == -1) {
     perror("write");
     return false;
   }
@@ -159,13 +156,12 @@
   // read() will return the entire message in one go, because it's a datagram
   // socket.
   constexpr size_t kBufSize = 1024 * 1024;
-  bssl::UniquePtr<uint8_t> buf((uint8_t *) OPENSSL_malloc(kBufSize));
-  ssize_t len = read_eintr(kFdControl, buf.get(), kBufSize);
+  std::vector<uint8_t> handoff(kBufSize);
+  ssize_t len = read_eintr(kFdControl, handoff.data(), handoff.size());
   if (len == -1) {
     perror("read");
     return 2;
   }
-  Span<uint8_t> handoff(buf.get(), len);
   if (!Handshaker(config, kFdProxyToHandshaker, kFdHandshakerToProxy, handoff,
                   kFdControl)) {
     return SignalError();
diff --git a/ssl/test/settings_writer.h b/ssl/test/settings_writer.h
index 322850d..179a5a4 100644
--- a/ssl/test/settings_writer.h
+++ b/ssl/test/settings_writer.h
@@ -20,7 +20,6 @@
 #include <openssl/bytestring.h>
 #include <openssl/ssl.h>
 
-#include "../internal.h"
 #include "test_config.h"
 
 struct SettingsWriter {