From 755ee7d82a26a1f85bdd315bb366fccf3feefa7d Mon Sep 17 00:00:00 2001
From: Anna Henningsen <anna@addaleax.net>
Date: Wed, 17 Jun 2020 01:46:19 +0200
Subject: [PATCH] quic: always copy stateless reset token

Take ownership of the token value, since the memory for it is allocated
anyway and the buffer size is just 16, i.e. copyable very cheaply.

This makes valgrind stop complaining about a use-after-free error
when running `sequential/test-quic-preferred-address-ipv6`.
---
 src/quic/node_quic_util-inl.h | 15 ++++++++++-----
 src/quic/node_quic_util.h     |  8 +++-----
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/src/quic/node_quic_util-inl.h b/src/quic/node_quic_util-inl.h
index dbd5648aecd3a5..d51dc8d7e63d23 100644
--- a/src/quic/node_quic_util-inl.h
+++ b/src/quic/node_quic_util-inl.h
@@ -287,22 +287,27 @@ bool PreferredAddress::ResolvePreferredAddress(
 StatelessResetToken::StatelessResetToken(
     uint8_t* token,
     const uint8_t* secret,
-    const QuicCID& cid) : token_(token) {
+    const QuicCID& cid) {
   GenerateResetToken(token, secret, cid);
+  memcpy(buf_, token, sizeof(buf_));
 }
 
 StatelessResetToken::StatelessResetToken(
     const uint8_t* secret,
-    const QuicCID& cid)
-    : token_(buf_) {
+    const QuicCID& cid)  {
   GenerateResetToken(buf_, secret, cid);
 }
 
+StatelessResetToken::StatelessResetToken(
+    const uint8_t* token) {
+  memcpy(buf_, token, sizeof(buf_));
+}
+
 std::string StatelessResetToken::ToString() const {
   std::vector<char> dest(NGTCP2_STATELESS_RESET_TOKENLEN * 2 + 1);
   dest[dest.size() - 1] = '\0';
   size_t written = StringBytes::hex_encode(
-      reinterpret_cast<const char*>(token_),
+      reinterpret_cast<const char*>(buf_),
       NGTCP2_STATELESS_RESET_TOKENLEN,
       dest.data(),
       dest.size());
@@ -313,7 +318,7 @@ size_t StatelessResetToken::Hash::operator()(
     const StatelessResetToken& token) const {
   size_t hash = 0;
   for (size_t n = 0; n < NGTCP2_STATELESS_RESET_TOKENLEN; n++)
-    hash ^= std::hash<uint8_t>{}(token.token_[n]) + 0x9e3779b9 +
+    hash ^= std::hash<uint8_t>{}(token.buf_[n]) + 0x9e3779b9 +
             (hash << 6) + (hash >> 2);
   return hash;
 }
diff --git a/src/quic/node_quic_util.h b/src/quic/node_quic_util.h
index 6fdfb99cc688a3..e1490941aa3224 100644
--- a/src/quic/node_quic_util.h
+++ b/src/quic/node_quic_util.h
@@ -386,13 +386,12 @@ class StatelessResetToken : public MemoryRetainer {
       const uint8_t* secret,
       const QuicCID& cid);
 
-  explicit StatelessResetToken(
-      const uint8_t* token)
-      : token_(token) {}
+  explicit inline StatelessResetToken(
+      const uint8_t* token);
 
   inline std::string ToString() const;
 
-  const uint8_t* data() const { return token_; }
+  const uint8_t* data() const { return buf_; }
 
   struct Hash {
     inline size_t operator()(const StatelessResetToken& token) const;
@@ -414,7 +413,6 @@ class StatelessResetToken : public MemoryRetainer {
 
  private:
   uint8_t buf_[NGTCP2_STATELESS_RESET_TOKENLEN]{};
-  const uint8_t* token_;
 };
 
 template <typename T>