Fix use after free in UdpPort
SendStunBindingRequest can cause a SocketAddress pointed to by the
iterator to be deleted asynchronously before returning, causing `it`
to be invalid when incrementing in the continuation step.
Bug: webrtc:7309, webrtc:14131
Change-Id: I3f7d3d7c12935d9592ef3642679a821c58826df9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/270744
Commit-Queue: Sameer Vijaykar <samvi@google.com>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37741}
diff --git a/p2p/base/stun_port.cc b/p2p/base/stun_port.cc
index 8074cbe..44e1243 100644
--- a/p2p/base/stun_port.cc
+++ b/p2p/base/stun_port.cc
@@ -424,8 +424,13 @@
RTC_DCHECK(request_manager_.empty());
for (ServerAddresses::const_iterator it = server_addresses_.begin();
- it != server_addresses_.end(); ++it) {
- SendStunBindingRequest(*it);
+ it != server_addresses_.end();) {
+ // sending a STUN binding request may cause the current SocketAddress to be
+ // erased from the set, invalidating the loop iterator before it is
+ // incremented (even if the SocketAddress itself still exists). So make a
+ // copy of the loop iterator, which may be safely invalidated.
+ ServerAddresses::const_iterator addr = it++;
+ SendStunBindingRequest(*addr);
}
}
diff --git a/p2p/base/stun_port.h b/p2p/base/stun_port.h
index 7a3239e..364aed6 100644
--- a/p2p/base/stun_port.h
+++ b/p2p/base/stun_port.h
@@ -210,6 +210,9 @@
void ResolveStunAddress(const rtc::SocketAddress& stun_addr);
void OnResolveResult(const rtc::SocketAddress& input, int error);
+ // Send a STUN binding request to the given address. Calling this method may
+ // cause the set of known server addresses to be modified, eg. by replacing an
+ // unresolved server address with a resolved address.
void SendStunBindingRequest(const rtc::SocketAddress& stun_addr);
// Below methods handles binding request responses.
diff --git a/p2p/base/stun_port_unittest.cc b/p2p/base/stun_port_unittest.cc
index a5e13f9..86dd64e 100644
--- a/p2p/base/stun_port_unittest.cc
+++ b/p2p/base/stun_port_unittest.cc
@@ -307,13 +307,7 @@
};
// Test that we can get an address from a STUN server specified by a hostname.
-// Crashes on Linux, see webrtc:7416
-#if defined(WEBRTC_LINUX) || defined(WEBRTC_WIN) || defined(WEBRTC_MAC)
-#define MAYBE_TestPrepareAddressHostname DISABLED_TestPrepareAddressHostname
-#else
-#define MAYBE_TestPrepareAddressHostname TestPrepareAddressHostname
-#endif
-TEST_F(StunPortWithMockDnsResolverTest, MAYBE_TestPrepareAddressHostname) {
+TEST_F(StunPortWithMockDnsResolverTest, TestPrepareAddressHostname) {
SetDnsResolverExpectations(
[](webrtc::MockAsyncDnsResolver* resolver,
webrtc::MockAsyncDnsResolverResult* resolver_result) {
@@ -625,8 +619,7 @@
};
// Test that we can get an address from a STUN server specified by a hostname.
-// Crashes on Linux, see webrtc:7416
-TEST_F(StunIPv6PortTestWithMockDnsResolver, MAYBE_TestPrepareAddressHostname) {
+TEST_F(StunIPv6PortTestWithMockDnsResolver, TestPrepareAddressHostname) {
SetDnsResolverExpectations(
[](webrtc::MockAsyncDnsResolver* resolver,
webrtc::MockAsyncDnsResolverResult* resolver_result) {