From 9de618d644c419d2a3452db33363d842d2401f73 Mon Sep 17 00:00:00 2001
From: zzz <zzz@i2pmail.org>
Date: Fri, 10 Jun 2022 07:50:43 -0400
Subject: [PATCH] SSU2: Catch errors on bad ack blocks

so rest of payload can be processed
Improve debug output on errors
---
 .../i2p/router/transport/udp/PeerState2.java  | 19 +++++++++++++------
 .../router/transport/udp/SSU2Bitfield.java    |  2 +-
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/router/java/src/net/i2p/router/transport/udp/PeerState2.java b/router/java/src/net/i2p/router/transport/udp/PeerState2.java
index 526cfe0697..a37c945e8c 100644
--- a/router/java/src/net/i2p/router/transport/udp/PeerState2.java
+++ b/router/java/src/net/i2p/router/transport/udp/PeerState2.java
@@ -567,12 +567,19 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
                 _log.debug("Got dup ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
             return;
         }
-        SSU2Bitfield ackbf;
-        ackbf = SSU2Bitfield.fromACKBlock(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0));
-        if (_log.shouldDebug())
-            _log.debug("Got new ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
-        // calls bitSet() below
-        ackbf.forEachAndNot(_ackedMessages, this);
+        try {
+            SSU2Bitfield ackbf = SSU2Bitfield.fromACKBlock(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0));
+            if (_log.shouldDebug())
+                _log.debug("Got new ACK block: " + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)));
+            // calls bitSet() below
+            ackbf.forEachAndNot(_ackedMessages, this);
+        } catch (Exception e) {
+            // IllegalArgumentException, buggy ack block, let the other blocks get processed
+            if (_log.shouldWarn())
+                _log.warn("Bad ACK block\n" + SSU2Bitfield.toString(ackThru, acks, ranges, (ranges != null ? ranges.length / 2 : 0)) +
+                          "\nAck through " + ackThru + " acks " + acks + (ranges != null ? "\n" + HexDump.dump(ranges) : "") +
+                          "\nfrom " + this, e);
+        }
     }
 
     public void gotTermination(int reason, long count) {
diff --git a/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java b/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java
index bbad4ed277..df14fe2b44 100644
--- a/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java
+++ b/router/java/src/net/i2p/router/transport/udp/SSU2Bitfield.java
@@ -36,7 +36,7 @@ class SSU2Bitfield {
      */
     public SSU2Bitfield(int size, long offset) {
         if (size <= 0 || offset < 0)
-            throw new IllegalArgumentException();
+            throw new IllegalArgumentException("size " + size + " offset " + offset);
         // force mult. of 256
         size = (size + 255) & 0x7FFFFF00;
         this.size = size;
-- 
GitLab