Avoid use-after-move in PeerConnection::Set[Local/Remote]Description.

In Set[Local/Remote]Description we have a raw pointer |desc| whose
ownership is passed to a helper function. Before this CL we continue
to use |desc| after ownership is passed under the assumption that the
object is not deleted.

In this CL, we instead rely on [local/remote]_description() after the
helper function has been called. In practice, this is a pointer to
the same object, but it removes the assumption about |desc| being
valid after its ownership is passed.

Bug: None
Change-Id: I144a190ea00f303f4713b64c45aa3e811c0f4b2e
Reviewed-on: https://webrtc-review.googlesource.com/21320
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#20654}
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index 3ea4a3f..e8857a3 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -1423,7 +1423,7 @@
   std::unique_ptr<SessionDescriptionInterface> desc_temp(desc);
 
   if (IsClosed()) {
-    std::string error = "Failed to set local " + desc->type() +
+    std::string error = "Failed to set local " + desc_temp->type() +
                         " sdp: Called in wrong state: STATE_CLOSED";
     RTC_LOG(LS_ERROR) << error;
     PostSetSessionDescriptionFailure(observer, error);
@@ -1434,10 +1434,13 @@
   // streams that might be removed by updating the session description.
   stats_->UpdateStats(kStatsOutputLevelStandard);
   std::string error;
+  // Takes the ownership of |desc_temp|. On success, local_description() is
+  // updated to reflect the description that was passed in.
   if (!SetLocalDescription(std::move(desc_temp), &error)) {
     PostSetSessionDescriptionFailure(observer, error);
     return;
   }
+  RTC_DCHECK(local_description());
 
   // If setting the description decided our SSL role, allocate any necessary
   // SCTP sids.
@@ -1449,7 +1452,7 @@
   // Update state and SSRC of local MediaStreams and DataChannels based on the
   // local session description.
   const cricket::ContentInfo* audio_content =
-      GetFirstAudioContent(desc->description());
+      GetFirstAudioContent(local_description()->description());
   if (audio_content) {
     if (audio_content->rejected) {
       RemoveTracks(cricket::MEDIA_TYPE_AUDIO);
@@ -1462,7 +1465,7 @@
   }
 
   const cricket::ContentInfo* video_content =
-      GetFirstVideoContent(desc->description());
+      GetFirstVideoContent(local_description()->description());
   if (video_content) {
     if (video_content->rejected) {
       RemoveTracks(cricket::MEDIA_TYPE_VIDEO);
@@ -1475,7 +1478,7 @@
   }
 
   const cricket::ContentInfo* data_content =
-      GetFirstDataContent(desc->description());
+      GetFirstDataContent(local_description()->description());
   if (data_content) {
     const cricket::DataContentDescription* data_desc =
         static_cast<const cricket::DataContentDescription*>(
@@ -1500,7 +1503,7 @@
   // before signaling that SetLocalDescription completed.
   transport_controller_->MaybeStartGathering();
 
-  if (desc->type() == SessionDescriptionInterface::kAnswer) {
+  if (local_description()->type() == SessionDescriptionInterface::kAnswer) {
     // TODO(deadbeef): We already had to hop to the network thread for
     // MaybeStartGathering...
     network_thread()->Invoke<void>(
@@ -1527,7 +1530,7 @@
   std::unique_ptr<SessionDescriptionInterface> desc_temp(desc);
 
   if (IsClosed()) {
-    std::string error = "Failed to set remote " + desc->type() +
+    std::string error = "Failed to set remote " + desc_temp->type() +
                         " sdp: Called in wrong state: STATE_CLOSED";
     RTC_LOG(LS_ERROR) << error;
     PostSetSessionDescriptionFailure(observer, error);
@@ -1538,10 +1541,13 @@
   // streams that might be removed by updating the session description.
   stats_->UpdateStats(kStatsOutputLevelStandard);
   std::string error;
+  // Takes the ownership of |desc_temp|. On success, remote_description() is
+  // updated to reflect the description that was passed in.
   if (!SetRemoteDescription(std::move(desc_temp), &error)) {
     PostSetSessionDescriptionFailure(observer, error);
     return;
   }
+  RTC_DCHECK(remote_description());
 
   // If setting the description decided our SSL role, allocate any necessary
   // SCTP sids.
@@ -1550,19 +1556,20 @@
     AllocateSctpSids(role);
   }
 
-  const cricket::SessionDescription* remote_desc = desc->description();
-  const cricket::ContentInfo* audio_content = GetFirstAudioContent(remote_desc);
-  const cricket::ContentInfo* video_content = GetFirstVideoContent(remote_desc);
+  const cricket::ContentInfo* audio_content =
+      GetFirstAudioContent(remote_description()->description());
+  const cricket::ContentInfo* video_content =
+      GetFirstVideoContent(remote_description()->description());
   const cricket::AudioContentDescription* audio_desc =
-      GetFirstAudioContentDescription(remote_desc);
+      GetFirstAudioContentDescription(remote_description()->description());
   const cricket::VideoContentDescription* video_desc =
-      GetFirstVideoContentDescription(remote_desc);
+      GetFirstVideoContentDescription(remote_description()->description());
   const cricket::DataContentDescription* data_desc =
-      GetFirstDataContentDescription(remote_desc);
+      GetFirstDataContentDescription(remote_description()->description());
 
   // Check if the descriptions include streams, just in case the peer supports
   // MSID, but doesn't indicate so with "a=msid-semantic".
-  if (remote_desc->msid_supported() ||
+  if (remote_description()->description()->msid_supported() ||
       (audio_desc && !audio_desc->streams().empty()) ||
       (video_desc && !video_desc->streams().empty())) {
     remote_peer_supports_msid_ = true;
@@ -1631,7 +1638,7 @@
   signaling_thread()->Post(RTC_FROM_HERE, this,
                            MSG_SET_SESSIONDESCRIPTION_SUCCESS, msg);
 
-  if (desc->type() == SessionDescriptionInterface::kAnswer) {
+  if (remote_description()->type() == SessionDescriptionInterface::kAnswer) {
     // TODO(deadbeef): We already had to hop to the network thread for
     // MaybeStartGathering...
     network_thread()->Invoke<void>(