Use absl::optional<StatelessResetToken> in place of a separate boolean and token on QuicConnection::PathState.
This will fix UndefinedBehaviorSanitizer crash in b/204901337 due to QuicConnection::FindMatchingOrNewClientConnectionIdOrToken not always set the value of *stateless_reset_token_received.
PiperOrigin-RevId: 407201586
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index fdecddc..7c4f004 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -242,8 +242,7 @@
default_path_(initial_self_address, QuicSocketAddress(),
/*client_connection_id=*/EmptyQuicConnectionId(),
server_connection_id,
- /*stateless_reset_token_received=*/false,
- /*stateless_reset_token=*/{}),
+ /*stateless_reset_token=*/absl::nullopt),
active_effective_peer_migration_type_(NO_CHANGE),
support_key_update_for_connection_(false),
last_packet_decrypted_(false),
@@ -615,7 +614,6 @@
no_stop_waiting_frames_ = true;
}
if (config.HasReceivedStatelessResetToken()) {
- default_path_.stateless_reset_token_received = true;
default_path_.stateless_reset_token = config.ReceivedStatelessResetToken();
}
if (config.HasReceivedAckDelayExponent()) {
@@ -1942,7 +1940,6 @@
QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
<< unused_cid_data->connection_id << " to default path";
default_path_.client_connection_id = unused_cid_data->connection_id;
- default_path_.stateless_reset_token_received = true;
default_path_.stateless_reset_token =
unused_cid_data->stateless_reset_token;
QUICHE_DCHECK(!packet_creator_.HasPendingFrames());
@@ -1960,7 +1957,6 @@
QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
<< unused_cid_data->connection_id << " to alternative path";
alternative_path_.client_connection_id = unused_cid_data->connection_id;
- alternative_path_.stateless_reset_token_received = true;
alternative_path_.stateless_reset_token =
unused_cid_data->stateless_reset_token;
}
@@ -2297,9 +2293,9 @@
bool QuicConnection::IsValidStatelessResetToken(
const StatelessResetToken& token) const {
QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
- return default_path_.stateless_reset_token_received &&
- QuicUtils::AreStatelessResetTokensEqual(
- token, default_path_.stateless_reset_token);
+ return default_path_.stateless_reset_token.has_value() &&
+ QuicUtils::AreStatelessResetTokensEqual(
+ token, *default_path_.stateless_reset_token);
}
void QuicConnection::OnAuthenticatedIetfStatelessResetPacket(
@@ -2968,25 +2964,19 @@
}
void QuicConnection::FindMatchingOrNewClientConnectionIdOrToken(
- const PathState& default_path,
- const PathState& alternative_path,
+ const PathState& default_path, const PathState& alternative_path,
const QuicConnectionId& server_connection_id,
QuicConnectionId* client_connection_id,
- bool* stateless_reset_token_received,
- StatelessResetToken* stateless_reset_token) {
+ absl::optional<StatelessResetToken>* stateless_reset_token) {
QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
if (peer_issued_cid_manager_ == nullptr ||
server_connection_id == default_path.server_connection_id) {
*client_connection_id = default_path.client_connection_id;
- *stateless_reset_token_received =
- default_path.stateless_reset_token_received;
*stateless_reset_token = default_path.stateless_reset_token;
return;
}
if (server_connection_id == alternative_path_.server_connection_id) {
*client_connection_id = alternative_path.client_connection_id;
- *stateless_reset_token_received =
- alternative_path.stateless_reset_token_received;
*stateless_reset_token = alternative_path.stateless_reset_token;
return;
}
@@ -3001,7 +2991,6 @@
}
*client_connection_id = connection_id_data->connection_id;
*stateless_reset_token = connection_id_data->stateless_reset_token;
- *stateless_reset_token_received = true;
}
bool QuicConnection::FindOnPathConnectionIds(
@@ -5359,17 +5348,15 @@
SetDefaultPathState(std::move(alternative_path_));
} else {
QuicConnectionId client_connection_id;
- bool stateless_reset_token_received = false;
- StatelessResetToken stateless_reset_token;
+ absl::optional<StatelessResetToken> stateless_reset_token;
FindMatchingOrNewClientConnectionIdOrToken(
previous_default_path, alternative_path_,
last_packet_destination_connection_id_, &client_connection_id,
- &stateless_reset_token_received, &stateless_reset_token);
- SetDefaultPathState(
- PathState(last_received_packet_info_.destination_address,
- current_effective_peer_address, client_connection_id,
- last_packet_destination_connection_id_,
- stateless_reset_token_received, stateless_reset_token));
+ &stateless_reset_token);
+ SetDefaultPathState(PathState(
+ last_received_packet_info_.destination_address,
+ current_effective_peer_address, client_connection_id,
+ last_packet_destination_connection_id_, stateless_reset_token));
// The path is considered validated if its peer IP address matches any
// validated path's peer IP address.
default_path_.validated =
@@ -5577,17 +5564,15 @@
<< last_received_packet_info_.destination_address;
if (!validate_client_addresses_) {
QuicConnectionId client_cid;
- bool stateless_reset_token_received = false;
- StatelessResetToken stateless_reset_token;
+ absl::optional<StatelessResetToken> stateless_reset_token;
FindMatchingOrNewClientConnectionIdOrToken(
default_path_, alternative_path_,
last_packet_destination_connection_id_, &client_cid,
- &stateless_reset_token_received, &stateless_reset_token);
- alternative_path_ =
- PathState(last_received_packet_info_.destination_address,
- current_effective_peer_address, client_cid,
- last_packet_destination_connection_id_,
- stateless_reset_token_received, stateless_reset_token);
+ &stateless_reset_token);
+ alternative_path_ = PathState(
+ last_received_packet_info_.destination_address,
+ current_effective_peer_address, client_cid,
+ last_packet_destination_connection_id_, stateless_reset_token);
} else if (!default_path_.validated) {
QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 4, 6);
// Skip reverse path validation because either handshake hasn't
@@ -5605,20 +5590,18 @@
} else if (!IsReceivedPeerAddressValidated()) {
QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 5, 6);
QuicConnectionId client_connection_id;
- bool stateless_reset_token_received;
- StatelessResetToken stateless_reset_token;
+ absl::optional<StatelessResetToken> stateless_reset_token;
FindMatchingOrNewClientConnectionIdOrToken(
default_path_, alternative_path_,
last_packet_destination_connection_id_, &client_connection_id,
- &stateless_reset_token_received, &stateless_reset_token);
+ &stateless_reset_token);
// Only override alternative path state upon receiving a PATH_CHALLENGE
// from an unvalidated peer address, and the connection isn't validating
// a recent peer migration.
- alternative_path_ =
- PathState(last_received_packet_info_.destination_address,
- current_effective_peer_address, client_connection_id,
- last_packet_destination_connection_id_,
- stateless_reset_token_received, stateless_reset_token);
+ alternative_path_ = PathState(
+ last_received_packet_info_.destination_address,
+ current_effective_peer_address, client_connection_id,
+ last_packet_destination_connection_id_, stateless_reset_token);
should_proactively_validate_peer_address_on_path_challenge_ = true;
}
}
@@ -6376,7 +6359,6 @@
*default_path_cid = unused_connection_id_data->connection_id;
default_path_.stateless_reset_token =
unused_connection_id_data->stateless_reset_token;
- default_path_.stateless_reset_token_received = true;
if (perspective_ == Perspective::IS_CLIENT) {
packet_creator_.SetServerConnectionId(
unused_connection_id_data->connection_id);
@@ -6388,8 +6370,6 @@
}
if (default_path_and_alternative_path_use_the_same_peer_connection_id) {
*alternative_path_cid = *default_path_cid;
- alternative_path_.stateless_reset_token_received =
- default_path_.stateless_reset_token_received;
alternative_path_.stateless_reset_token =
default_path_.stateless_reset_token;
} else if (!alternative_path_cid->IsEmpty() &&
@@ -6402,7 +6382,6 @@
*alternative_path_cid = unused_connection_id_data->connection_id;
alternative_path_.stateless_reset_token =
unused_connection_id_data->stateless_reset_token;
- alternative_path_.stateless_reset_token_received = true;
}
}
@@ -6585,7 +6564,6 @@
alternative_path_ = PathState(
context->self_address(), context->peer_address(),
default_path_.client_connection_id, default_path_.server_connection_id,
- default_path_.stateless_reset_token_received,
default_path_.stateless_reset_token);
}
if (path_validator_.HasPendingPathValidation()) {
@@ -6611,8 +6589,7 @@
return;
}
QuicConnectionId client_connection_id, server_connection_id;
- StatelessResetToken stateless_reset_token;
- bool stateless_reset_token_received = false;
+ absl::optional<StatelessResetToken> stateless_reset_token;
if (self_issued_cid_manager_ != nullptr) {
client_connection_id =
*self_issued_cid_manager_->ConsumeOneConnectionId();
@@ -6621,13 +6598,11 @@
const auto* connection_id_data =
peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
server_connection_id = connection_id_data->connection_id;
- stateless_reset_token_received = true;
stateless_reset_token = connection_id_data->stateless_reset_token;
}
- alternative_path_ =
- PathState(context->self_address(), context->peer_address(),
- client_connection_id, server_connection_id,
- stateless_reset_token_received, stateless_reset_token);
+ alternative_path_ = PathState(context->self_address(),
+ context->peer_address(), client_connection_id,
+ server_connection_id, stateless_reset_token);
}
path_validator_.StartPathValidation(std::move(context),
std::move(result_delegate));
@@ -6723,8 +6698,6 @@
default_path_.server_connection_id = alternative_path_.server_connection_id;
default_path_.stateless_reset_token =
alternative_path_.stateless_reset_token;
- default_path_.stateless_reset_token_received =
- alternative_path_.stateless_reset_token_received;
return true;
}
// Client migration is without path validation.
@@ -6748,7 +6721,6 @@
const auto* connection_id_data =
peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
default_path_.server_connection_id = connection_id_data->connection_id;
- default_path_.stateless_reset_token_received = true;
default_path_.stateless_reset_token =
connection_id_data->stateless_reset_token;
}
@@ -6961,12 +6933,12 @@
peer_address = QuicSocketAddress();
client_connection_id = {};
server_connection_id = {};
- stateless_reset_token_received = false;
validated = false;
bytes_received_before_address_validation = 0;
bytes_sent_before_address_validation = 0;
send_algorithm = nullptr;
rtt_stats = absl::nullopt;
+ stateless_reset_token.reset();
}
QuicConnection::PathState::PathState(PathState&& other) {
@@ -6980,7 +6952,6 @@
peer_address = other.peer_address;
client_connection_id = other.client_connection_id;
server_connection_id = other.server_connection_id;
- stateless_reset_token_received = other.stateless_reset_token_received;
stateless_reset_token = other.stateless_reset_token;
validated = other.validated;
bytes_received_before_address_validation =
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index e27b6cf..1d9bf95 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -1365,14 +1365,12 @@
const QuicSocketAddress& alternative_peer_address,
const QuicConnectionId& client_connection_id,
const QuicConnectionId& server_connection_id,
- bool stateless_reset_token_received,
- StatelessResetToken stateless_reset_token)
+ absl::optional<StatelessResetToken> stateless_reset_token)
: self_address(alternative_self_address),
peer_address(alternative_peer_address),
client_connection_id(client_connection_id),
server_connection_id(server_connection_id),
- stateless_reset_token(stateless_reset_token),
- stateless_reset_token_received(stateless_reset_token_received) {}
+ stateless_reset_token(stateless_reset_token) {}
PathState(PathState&& other);
@@ -1386,8 +1384,7 @@
QuicSocketAddress peer_address;
QuicConnectionId client_connection_id;
QuicConnectionId server_connection_id;
- StatelessResetToken stateless_reset_token;
- bool stateless_reset_token_received = false;
+ absl::optional<StatelessResetToken> stateless_reset_token;
// True if the peer address has been validated. Address is considered
// validated when 1) an address token of the peer address is received and
// validated, or 2) a HANDSHAKE packet has been successfully processed on
@@ -1524,12 +1521,10 @@
// client connection ID used on default/alternative path. If not, find if
// there is an unused connection ID.
void FindMatchingOrNewClientConnectionIdOrToken(
- const PathState& default_path,
- const PathState& alternative_path,
+ const PathState& default_path, const PathState& alternative_path,
const QuicConnectionId& server_connection_id,
QuicConnectionId* client_connection_id,
- bool* stateless_reset_token_received,
- StatelessResetToken* stateless_reset_token);
+ absl::optional<StatelessResetToken>* stateless_reset_token);
// Returns true and sets connection IDs if (self_address, peer_address)
// corresponds to either the default path or alternative path. Returns false
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 946bda9..1e3b70d 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -2318,7 +2318,7 @@
EXPECT_EQ(default_path->client_connection_id, client_cid0);
EXPECT_EQ(default_path->server_connection_id, server_cid0);
EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
- EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ EXPECT_FALSE(alternative_path->stateless_reset_token.has_value());
auto* retire_peer_issued_cid_alarm =
connection_.GetRetirePeerIssuedConnectionIdAlarm();
ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
@@ -14232,7 +14232,7 @@
// Verify that alternative_path_ is cleared and the peer CID is retired.
EXPECT_TRUE(alternative_path->client_connection_id.IsEmpty());
EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
- EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ EXPECT_FALSE(alternative_path->stateless_reset_token.has_value());
auto* retire_peer_issued_cid_alarm =
connection_.GetRetirePeerIssuedConnectionIdAlarm();
ASSERT_TRUE(retire_peer_issued_cid_alarm->IsSet());
@@ -14341,7 +14341,7 @@
EXPECT_EQ(packet_creator->GetSourceConnectionId(), server_cid1);
// Verify that alternative_path_ is cleared.
EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
- EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ EXPECT_FALSE(alternative_path->stateless_reset_token.has_value());
// Switch to use the mock send algorithm.
send_algorithm_ = new StrictMock<MockSendAlgorithm>();
@@ -14511,12 +14511,11 @@
EXPECT_EQ(default_path->client_connection_id, client_cid1);
EXPECT_EQ(default_path->server_connection_id, server_cid1);
EXPECT_EQ(default_path->stateless_reset_token, frame1.stateless_reset_token);
- EXPECT_TRUE(default_path->stateless_reset_token_received);
const auto* alternative_path =
QuicConnectionPeer::GetAlternativePath(&connection_);
EXPECT_TRUE(alternative_path->client_connection_id.IsEmpty());
EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
- EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ EXPECT_FALSE(alternative_path->stateless_reset_token.has_value());
ASSERT_EQ(packet_creator->GetDestinationConnectionId(), server_cid1);
// Client will retire server connection ID on old default_path.
@@ -14587,7 +14586,7 @@
QuicConnectionPeer::GetAlternativePath(&connection_);
EXPECT_TRUE(alternative_path->client_connection_id.IsEmpty());
EXPECT_TRUE(alternative_path->server_connection_id.IsEmpty());
- EXPECT_FALSE(alternative_path->stateless_reset_token_received);
+ EXPECT_FALSE(alternative_path->stateless_reset_token.has_value());
// Client will retire server connection ID on alternative_path.
auto* retire_peer_issued_cid_alarm =
@@ -14664,7 +14663,6 @@
EXPECT_EQ(default_path->client_connection_id, new_client_connection_id);
EXPECT_EQ(default_path->server_connection_id, frame1.connection_id);
EXPECT_EQ(default_path->stateless_reset_token, frame1.stateless_reset_token);
- EXPECT_TRUE(default_path->stateless_reset_token_received);
// Client will retire server connection ID on old default_path.
auto* retire_peer_issued_cid_alarm =
@@ -15060,7 +15058,7 @@
alternative_path->peer_address = QuicSocketAddress(new_host, 12345);
alternative_path->server_connection_id = TestConnectionId(3);
ASSERT_TRUE(alternative_path->client_connection_id.IsEmpty());
- ASSERT_FALSE(alternative_path->stateless_reset_token_received);
+ ASSERT_FALSE(alternative_path->stateless_reset_token.has_value());
QuicNewConnectionIdFrame frame;
frame.sequence_number = 1u;
@@ -15075,7 +15073,6 @@
ASSERT_EQ(alternative_path->client_connection_id, frame.connection_id);
ASSERT_EQ(alternative_path->stateless_reset_token,
frame.stateless_reset_token);
- ASSERT_TRUE(alternative_path->stateless_reset_token_received);
}
TEST_P(QuicConnectionTest, PatchMissingClientConnectionIdOntoDefaultPath) {
@@ -15103,7 +15100,7 @@
ASSERT_FALSE(default_path->validated);
ASSERT_TRUE(default_path->client_connection_id.IsEmpty());
- ASSERT_FALSE(default_path->stateless_reset_token_received);
+ ASSERT_FALSE(default_path->stateless_reset_token.has_value());
QuicNewConnectionIdFrame frame;
frame.sequence_number = 1u;
@@ -15117,7 +15114,6 @@
ASSERT_EQ(default_path->client_connection_id, frame.connection_id);
ASSERT_EQ(default_path->stateless_reset_token, frame.stateless_reset_token);
- ASSERT_TRUE(default_path->stateless_reset_token_received);
ASSERT_EQ(packet_creator->GetDestinationConnectionId(), frame.connection_id);
}