File: s0123.patch

package info (click to toggle)
firefox 147.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,683,320 kB
  • sloc: cpp: 7,607,359; javascript: 6,533,295; ansic: 3,775,223; python: 1,415,500; xml: 634,561; asm: 438,949; java: 186,241; sh: 62,752; makefile: 18,079; objc: 13,092; perl: 12,808; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; php: 436; lisp: 258; awk: 247; sql: 66; sed: 54; csh: 10; exp: 6
file content (68 lines) | stat: -rw-r--r-- 2,994 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
From: Michael Froman <mfroman@mozilla.com>
Date: Thu, 18 Sep 2025 12:09:00 -0500
Subject: Bug 1985396 - Cherry-pick upstream libwebrtc commit 63a59de808

Upstream commit: https://webrtc.googlesource.com/src/+/63a59de808ba7669e60bded703e71f360e5337e0
       dcsctp: Avoid iterator invalidation

       The ExpireOutstandingChunks method iterated through the
       `outstanding_data_` container while conditionally calling
       `AbandonAllFor`. The `AbandonAllFor` method can, in some cases, add new
       elements to `outstanding_data_`, which invalidates the iterators used by
       the loop in `ExpireOutstandingChunks`. This could lead to undefined
       behavior.

       This aligns the C++ implementation to the Rust dcsctp port, which
       handles this correctly by using a two-pass approach.

       Bug: chromium:443213199
       Change-Id: Ib5ac73b743c5ed900a69806088780c213536a4a6
       Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/408002
       Reviewed-by: Emil Lundmark <lndmrk@webrtc.org>
       Commit-Queue: Emil Lundmark <lndmrk@webrtc.org>
       Auto-Submit: Victor Boivie <boivie@webrtc.org>
       Cr-Commit-Position: refs/heads/main@{#45566}
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b85c57c2d6f0604075bf639a9a7342ece543cdf1
---
 net/dcsctp/tx/outstanding_data.cc | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/net/dcsctp/tx/outstanding_data.cc b/net/dcsctp/tx/outstanding_data.cc
index 074e3c0461..63e750b5fc 100644
--- a/net/dcsctp/tx/outstanding_data.cc
+++ b/net/dcsctp/tx/outstanding_data.cc
@@ -402,6 +402,7 @@ std::vector<std::pair<TSN, Data>> OutstandingData::GetChunksToBeRetransmitted(
 }
 
 void OutstandingData::ExpireOutstandingChunks(Timestamp now) {
+  std::vector<UnwrappedTSN> tsns_to_expire;
   UnwrappedTSN tsn = last_cumulative_tsn_ack_;
   for (const Item& item : outstanding_data_) {
     tsn.Increment();
@@ -411,15 +412,22 @@ void OutstandingData::ExpireOutstandingChunks(Timestamp now) {
     if (item.is_abandoned()) {
       // Already abandoned.
     } else if (item.is_nacked() && item.has_expired(now)) {
-      RTC_DLOG(LS_VERBOSE) << "Marking nacked chunk " << *tsn.Wrap()
-                           << " and message " << *item.data().mid
-                           << " as expired";
-      AbandonAllFor(item);
+      tsns_to_expire.push_back(tsn);
     } else {
       // A non-expired chunk. No need to iterate any further.
       break;
     }
   }
+
+  for (UnwrappedTSN tsn_to_expire : tsns_to_expire) {
+    // The item is retrieved by TSN, as AbandonAllFor may have modified
+    // `outstanding_data_` and invalidated iterators from the first loop.
+    Item& item = GetItem(tsn_to_expire);
+    RTC_DLOG(LS_WARNING) << "Marking nacked chunk " << *tsn_to_expire.Wrap()
+                         << " and message " << *item.data().mid
+                         << " as expired";
+    AbandonAllFor(item);
+  }
   RTC_DCHECK(IsConsistent());
 }