SSU2: Catch "shift too big" IAE from acked bitfield while sending termination

Add preliminary code to terminate session before
there are too many unacked messages to cause the IAE
(untested)
log tweaks

reported by drzed
This commit is contained in:
zzz
2022-12-14 14:42:12 -05:00
parent 4aa6d15933
commit e71ba76d98
2 changed files with 23 additions and 6 deletions

View File

@@ -304,9 +304,14 @@ class PacketBuilder2 {
packet.setPriority(priority);
if (fragments.isEmpty()) {
SSU2Bitfield acked = peer.getAckedMessages();
if (acked != null) // null for PeerStateDestroyed
acked.set(pktNum); // not ack-eliciting
SSU2Bitfield acked = peer.getAckedMessages();
if (acked != null) { // null for PeerStateDestroyed
try {
acked.set(pktNum); // not ack-eliciting
} catch (IndexOutOfBoundsException e) {
// shift too big, ignore, we're dead or about to be
}
}
packet.markType(1);
packet.setFragmentCount(-1);
packet.setMessageType(TYPE_ACK);
@@ -340,7 +345,11 @@ class PacketBuilder2 {
encryptDataPacket(packet, peer.getSendCipher(), pktNum, peer.getSendHeaderEncryptKey1(), peer.getSendHeaderEncryptKey2());
setTo(packet, peer.getRemoteIPAddress(), peer.getRemotePort());
packet.setPriority(PRIORITY_LOW);
peer.getAckedMessages().set(pktNum); // not ack-eliciting
try {
peer.getAckedMessages().set(pktNum); // not ack-eliciting
} catch (IndexOutOfBoundsException e) {
// shift too big, ignore, we're dead or about to be
}
return packet;
}

View File

@@ -216,6 +216,14 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
if (now >= _sentMessagesLastExpired + SENT_MESSAGES_CLEAN_TIME) {
_sentMessagesLastExpired = now;
if (!_sentMessages.isEmpty()) {
// TODO is this the right place for this check?
long ahead = _packetNumber.get() - _ackedMessages.getHighestSet();
if (ahead > BITFIELD_SIZE) {
if (_log.shouldWarn())
_log.warn("Fail after " + ahead + "unacked packets on " + this);
_transport.sendDestroy(this, REASON_FRAME_TIMEOUT);
_transport.dropPeer(this, true, "Too many unacked packets");
}
if (_log.shouldDebug())
_log.debug("finishMessages() over " + _sentMessages.size() + " pending acks");
loop:
@@ -227,8 +235,8 @@ public class PeerState2 extends PeerState implements SSU2Payload.PayloadCallback
continue loop;
}
iter.remove();
if (_log.shouldWarn())
_log.warn("Cleaned from sentMessages: " + frags);
if (_log.shouldInfo())
_log.info("Cleaned from sentMessages: " + frags);
}
}
}