Prevent transceiver crash during SDP local rejection Ensure that transceivers remain valid when handling locally rejected media content during SDP updates. Previously, the transceiver was std::move()ed out of the update vector prematurely, which could cause it to be destroyed before associated worker tasks had finished executing. Fixed: chromium:504194151 Change-Id: Id38ce125cbe83a4ea709adfd1951613642cafc8e Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/466140 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47528}
diff --git a/pc/peer_connection_jsep_unittest.cc b/pc/peer_connection_jsep_unittest.cc index 104591b..a4ebec6 100644 --- a/pc/peer_connection_jsep_unittest.cc +++ b/pc/peer_connection_jsep_unittest.cc
@@ -1031,6 +1031,20 @@ EXPECT_EQ(second_mid, caller_second_transceiver->mid()); } +TEST_F(PeerConnectionJsepTest, LocallyRejectedTransceiverDoesNotCrash) { + auto caller = CreatePeerConnection(); + auto transceiver = caller->AddTransceiver(MediaType::AUDIO); + + ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer())); + + transceiver->StopInternal(); + + // The reoffer will have a rejected media section. + // Setting it as local description triggers + // MaybeHandleLocallyRejectedTransceiver. + ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer())); +} + // Test that an m= section is *not* recycled if the media section is only // rejected in the pending remote description and there is no current local // description.
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc index c3a66d6..09f9ca5 100644 --- a/pc/sdp_offer_answer.cc +++ b/pc/sdp_offer_answer.cc
@@ -4311,9 +4311,11 @@ // Handle locally rejected content. This code path is only needed for apps // that SDP munge. Remote rejected content is handled in // ApplyRemoteDescriptionUpdateTransceiverState(). + // Do not use std::move here to ensure that the transceiver stays alive + // in the `transceivers_to_update` vector until the end of this function. + // This guarantees that it outlives the execution of `worker_tasks.Run()`. MaybeHandleLocallyRejectedTransceiver(source, new_session, update.content, - std::move(update.transceiver), - worker_tasks); + update.transceiver, worker_tasks); } error = network_teardown_tasks.Run();