From 0882efb5cbab0e6e86f518a179a6d0a0e844be65 Mon Sep 17 00:00:00 2001 From: Michiel ten Hagen Date: Wed, 26 May 2021 12:34:55 +0200 Subject: [PATCH] Support writing unsigned integers to buffer (#691) * Support writing unsigned integers to buffer, this is required to support channel ids greater than Integer.MAX_VALUE fixes hierynomus/sshj#690 * Fix incorrect test * Fix indentation to make codacy happy Co-authored-by: Jeroen van Erp --- .../java/net/schmizz/sshj/common/Buffer.java | 17 +++++++++++++++++ .../sshj/connection/ConnectionImpl.java | 2 +- .../connection/channel/AbstractChannel.java | 2 +- .../channel/ChannelInputStream.java | 2 +- .../channel/ChannelOutputStream.java | 2 +- .../net/schmizz/sshj/common/BufferTest.java | 19 +++++++++++++++++++ 6 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/schmizz/sshj/common/Buffer.java b/src/main/java/net/schmizz/sshj/common/Buffer.java index 169a8349..a47ddd37 100644 --- a/src/main/java/net/schmizz/sshj/common/Buffer.java +++ b/src/main/java/net/schmizz/sshj/common/Buffer.java @@ -306,6 +306,23 @@ public class Buffer> { data[rpos++] & 0x000000ffL; } + /** + * Writes a uint32 integer + * + * @param uint32 + * + * @return this + */ + @SuppressWarnings("unchecked") + public T putUInt32FromInt(int uint32) { + ensureCapacity(4); + data[wpos++] = (byte) (uint32 >> 24); + data[wpos++] = (byte) (uint32 >> 16); + data[wpos++] = (byte) (uint32 >> 8); + data[wpos++] = (byte) uint32; + return (T) this; + } + /** * Writes a uint32 integer * diff --git a/src/main/java/net/schmizz/sshj/connection/ConnectionImpl.java b/src/main/java/net/schmizz/sshj/connection/ConnectionImpl.java index cfaee366..59e47032 100644 --- a/src/main/java/net/schmizz/sshj/connection/ConnectionImpl.java +++ b/src/main/java/net/schmizz/sshj/connection/ConnectionImpl.java @@ -245,7 +245,7 @@ public class ConnectionImpl public void sendOpenFailure(int recipient, Reason reason, String message) throws TransportException { trans.write(new SSHPacket(Message.CHANNEL_OPEN_FAILURE) - .putUInt32(recipient) + .putUInt32FromInt(recipient) .putUInt32(reason.getCode()) .putString(message)); } diff --git a/src/main/java/net/schmizz/sshj/connection/channel/AbstractChannel.java b/src/main/java/net/schmizz/sshj/connection/channel/AbstractChannel.java index e31d0f4e..1cd3e5c9 100644 --- a/src/main/java/net/schmizz/sshj/connection/channel/AbstractChannel.java +++ b/src/main/java/net/schmizz/sshj/connection/channel/AbstractChannel.java @@ -352,7 +352,7 @@ public abstract class AbstractChannel } protected SSHPacket newBuffer(Message cmd) { - return new SSHPacket(cmd).putUInt32(recipient); + return new SSHPacket(cmd).putUInt32FromInt(recipient); } protected void receiveInto(ChannelInputStream stream, SSHPacket buf) diff --git a/src/main/java/net/schmizz/sshj/connection/channel/ChannelInputStream.java b/src/main/java/net/schmizz/sshj/connection/channel/ChannelInputStream.java index 6e79df0f..85f0024d 100644 --- a/src/main/java/net/schmizz/sshj/connection/channel/ChannelInputStream.java +++ b/src/main/java/net/schmizz/sshj/connection/channel/ChannelInputStream.java @@ -151,7 +151,7 @@ public final class ChannelInputStream if (adjustment > 0) { log.debug("Sending SSH_MSG_CHANNEL_WINDOW_ADJUST to #{} for {} bytes", chan.getRecipient(), adjustment); trans.write(new SSHPacket(Message.CHANNEL_WINDOW_ADJUST) - .putUInt32(chan.getRecipient()).putUInt32(adjustment)); + .putUInt32FromInt(chan.getRecipient()).putUInt32(adjustment)); win.expand(adjustment); } } diff --git a/src/main/java/net/schmizz/sshj/connection/channel/ChannelOutputStream.java b/src/main/java/net/schmizz/sshj/connection/channel/ChannelOutputStream.java index ad30493f..f3322389 100644 --- a/src/main/java/net/schmizz/sshj/connection/channel/ChannelOutputStream.java +++ b/src/main/java/net/schmizz/sshj/connection/channel/ChannelOutputStream.java @@ -90,7 +90,7 @@ public final class ChannelOutputStream extends OutputStream implements ErrorNoti packet.wpos(headerOffset); packet.putMessageID(Message.CHANNEL_DATA); - packet.putUInt32(chan.getRecipient()); + packet.putUInt32FromInt(chan.getRecipient()); packet.putUInt32(writeNow); packet.wpos(dataOffset + writeNow); diff --git a/src/test/java/net/schmizz/sshj/common/BufferTest.java b/src/test/java/net/schmizz/sshj/common/BufferTest.java index 7e61ad9a..15acb219 100644 --- a/src/test/java/net/schmizz/sshj/common/BufferTest.java +++ b/src/test/java/net/schmizz/sshj/common/BufferTest.java @@ -25,6 +25,25 @@ import static org.junit.Assert.*; public class BufferTest { + @Test + public void testNegativeInteger() throws BufferException { + byte[] negativeInt = new byte[] { (byte) 0xB8, + (byte) 0x4B, + (byte) 0xF4, + (byte) 0x38 }; + PlainBuffer buffer = new PlainBuffer(negativeInt); + assertEquals(buffer.readUInt32AsInt(),-1202981832); + + PlainBuffer buff = new PlainBuffer(); + buff.ensureCapacity(4); + buff.putUInt32FromInt(-1202981832); + byte[] data = buff.getCompactData(); + assertEquals(data[0], (byte) 0xB8); + assertEquals(data[1], (byte) 0x4B); + assertEquals(data[2], (byte) 0xF4); + assertEquals(data[3], (byte) 0x38); + } + // Issue 72: previously, it entered an infinite loop trying to establish the buffer size @Test public void shouldThrowOnTooLargeCapacity() {