summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-11-06 18:31:07 +0100
committerDirk Engling <erdgeist@erdgeist.org>2026-11-06 18:31:07 +0100
commitc965744e09a24270bb26e3e008dc2ede76544c98 (patch)
tree0ea105e7346f6d195b5e01ca171d721abffcf180
parent92c27bbda9e809683537e5cc48adad0d5c390587 (diff)
Fix: livesync watermark used sizeof(ot_peer) which is a byte. Clamping on copy length now
-rw-r--r--src/ot_livesync.c6
-rw-r--r--tests/integration/test_livesync.py13
2 files changed, 18 insertions, 1 deletions
diff --git a/src/ot_livesync.c b/src/ot_livesync.c
index 7d7208e..1381b3b 100644
--- a/src/ot_livesync.c
+++ b/src/ot_livesync.c
@@ -30,7 +30,7 @@ static uint16_t g_port = LIVESYNC_PORT;
30#define LIVESYNC_INCOMING_BUFFSIZE (256 * 256) 30#define LIVESYNC_INCOMING_BUFFSIZE (256 * 256)
31 31
32#define LIVESYNC_OUTGOING_BUFFSIZE_PEERS 1480 32#define LIVESYNC_OUTGOING_BUFFSIZE_PEERS 1480
33#define LIVESYNC_OUTGOING_WATERMARK_PEERS (sizeof(ot_peer) + sizeof(ot_hash)) 33#define LIVESYNC_OUTGOING_WATERMARK_PEERS (sizeof(ot_hash) + OT_PEER_SIZE6)
34 34
35#define LIVESYNC_MAXDELAY 15 /* seconds */ 35#define LIVESYNC_MAXDELAY 15 /* seconds */
36 36
@@ -127,6 +127,10 @@ static void livesync_issue_peersync(sync_buffer *buf) {
127 char mycopy[LIVESYNC_OUTGOING_BUFFSIZE_PEERS]; 127 char mycopy[LIVESYNC_OUTGOING_BUFFSIZE_PEERS];
128 size_t fill = buf->fill; 128 size_t fill = buf->fill;
129 129
130 /* The flush watermark keeps fill within the buffer */
131 if (fill > LIVESYNC_OUTGOING_BUFFSIZE_PEERS)
132 fill = LIVESYNC_OUTGOING_BUFFSIZE_PEERS;
133
130 memcpy(mycopy, buf->data, fill); 134 memcpy(mycopy, buf->data, fill);
131 buf->fill = sizeof(g_tracker_id) + sizeof(uint32_t); 135 buf->fill = sizeof(g_tracker_id) + sizeof(uint32_t);
132 buf->next_packet_time = time_future_seconds(LIVESYNC_MAXDELAY); 136 buf->next_packet_time = time_future_seconds(LIVESYNC_MAXDELAY);
diff --git a/tests/integration/test_livesync.py b/tests/integration/test_livesync.py
index f4cb2db..e146d93 100644
--- a/tests/integration/test_livesync.py
+++ b/tests/integration/test_livesync.py
@@ -72,6 +72,19 @@ class LiveSyncIn(TrackerTestCase):
72 self.assertTrue(self.tracker.wait_until(lambda: self.counts(info_hash) == (1, 0)), 72 self.assertTrue(self.tracker.wait_until(lambda: self.counts(info_hash) == (1, 0)),
73 "scrape says %r" % (self.counts(info_hash),)) 73 "scrape says %r" % (self.counts(info_hash),))
74 74
75 def test_many_v6_announces_do_not_overflow_the_send_buffer(self):
76 """The outgoing peer buffer is filled by announces to a clustered
77 tracker. The flush watermark used sizeof(ot_peer) (== 1), so a v6
78 record could be appended past the 1480-byte buffer onto the adjacent
79 fill field, which then drove an oversized stack copy. Well past the
80 old overflow point (~37 v6 peers) the tracker must still be alive."""
81 last = None
82 for i in range(80):
83 last = self.tracker.announce(self.hash_for("flood-%d" % i),
84 ip="2001:db8::%x" % (i + 1), port=7000 + i, left=1)
85 self.assertIn(b"complete", last, "the tracker stopped answering mid-flood")
86 # tearDown's stop() surfaces any sanitizer complaint on the way out.
87
75 def test_one_packet_carries_several_torrents(self): 88 def test_one_packet_carries_several_torrents(self):
76 hashes = [self.hash_for("sync-many-%d" % i) for i in range(4)] 89 hashes = [self.hash_for("sync-many-%d" % i) for i in range(4)]
77 self.tracker.livesync_send(packet(SYNC_PEER4, [(h, peer4("10.1.2.%d" % (5 + i), 6881, FLAG_SEEDING)) 90 self.tracker.livesync_send(packet(SYNC_PEER4, [(h, peer4("10.1.2.%d" % (5 + i), 6881, FLAG_SEEDING))