From cc4fa2bbc833f4a141e8140004f28df8d329c027 Mon Sep 17 00:00:00 2001 From: Wim Dumon Date: Wed, 28 Apr 2021 17:47:58 +0200 Subject: [PATCH 01/37] Offer option to disable traversalLimitInWords Use case: large trusted input data file, mapped in memory by MappedByteBuffer, which is often re-queried so a sensible limit cannot be set. --- runtime/src/main/java/org/capnproto/ReaderArena.java | 8 +++++--- runtime/src/main/java/org/capnproto/Serialize.java | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/runtime/src/main/java/org/capnproto/ReaderArena.java b/runtime/src/main/java/org/capnproto/ReaderArena.java index 13c9c87..63d8aa2 100644 --- a/runtime/src/main/java/org/capnproto/ReaderArena.java +++ b/runtime/src/main/java/org/capnproto/ReaderArena.java @@ -45,11 +45,13 @@ public final class ReaderArena implements Arena { } @Override - public final void checkReadLimit(int numBytes) { - if (numBytes > limit) { + public final void checkReadLimit(int numWords) { + if (limit == -1) { + return; + } else if (numWords > limit) { throw new DecodeException("Read limit exceeded."); } else { - limit -= numBytes; + limit -= numWords; } } } diff --git a/runtime/src/main/java/org/capnproto/Serialize.java b/runtime/src/main/java/org/capnproto/Serialize.java index 7dbfac0..4d9aeaa 100644 --- a/runtime/src/main/java/org/capnproto/Serialize.java +++ b/runtime/src/main/java/org/capnproto/Serialize.java @@ -145,7 +145,7 @@ public final class Serialize { } bb.position(segmentBase + totalWords * Constants.BYTES_PER_WORD); - if (totalWords > options.traversalLimitInWords) { + if (options.traversalLimitInWords != -1 && totalWords > options.traversalLimitInWords) { throw new DecodeException("Message size exceeds traversal limit."); } From 9293ef5bf678ac2ba0029f11806cd652d04ea235 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Sun, 9 May 2021 14:31:32 -0400 Subject: [PATCH 02/37] get things compiling again --- compiler/pom.xml | 2 ++ .../src/test/java/org/capnproto/{ => test}/EncodingTest.java | 0 compiler/src/test/java/org/capnproto/{ => test}/TestUtil.java | 0 3 files changed, 2 insertions(+) rename compiler/src/test/java/org/capnproto/{ => test}/EncodingTest.java (100%) rename compiler/src/test/java/org/capnproto/{ => test}/TestUtil.java (100%) diff --git a/compiler/pom.xml b/compiler/pom.xml index d8ff54e..afac45e 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -31,6 +31,8 @@ UTF-8 + 1.8 + 1.8 diff --git a/compiler/src/test/java/org/capnproto/EncodingTest.java b/compiler/src/test/java/org/capnproto/test/EncodingTest.java similarity index 100% rename from compiler/src/test/java/org/capnproto/EncodingTest.java rename to compiler/src/test/java/org/capnproto/test/EncodingTest.java diff --git a/compiler/src/test/java/org/capnproto/TestUtil.java b/compiler/src/test/java/org/capnproto/test/TestUtil.java similarity index 100% rename from compiler/src/test/java/org/capnproto/TestUtil.java rename to compiler/src/test/java/org/capnproto/test/TestUtil.java From 07e47d41044f96d212408122304cae2b3ad6a325 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Sun, 9 May 2021 14:53:54 -0400 Subject: [PATCH 03/37] add some documentation about the new 'no limit' option --- runtime/src/main/java/org/capnproto/Arena.java | 2 +- runtime/src/main/java/org/capnproto/ReaderArena.java | 3 ++- .../src/main/java/org/capnproto/ReaderOptions.java | 11 +++++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/runtime/src/main/java/org/capnproto/Arena.java b/runtime/src/main/java/org/capnproto/Arena.java index bb6c42e..2866f61 100644 --- a/runtime/src/main/java/org/capnproto/Arena.java +++ b/runtime/src/main/java/org/capnproto/Arena.java @@ -23,5 +23,5 @@ package org.capnproto; public interface Arena { public SegmentReader tryGetSegment(int id); - public void checkReadLimit(int numBytes); + public void checkReadLimit(int numWords); } diff --git a/runtime/src/main/java/org/capnproto/ReaderArena.java b/runtime/src/main/java/org/capnproto/ReaderArena.java index 63d8aa2..c499401 100644 --- a/runtime/src/main/java/org/capnproto/ReaderArena.java +++ b/runtime/src/main/java/org/capnproto/ReaderArena.java @@ -26,8 +26,8 @@ import java.nio.ByteBuffer; public final class ReaderArena implements Arena { + // Current limit. -1 means no limit. public long limit; - // current limit public final ArrayList segments; @@ -47,6 +47,7 @@ public final class ReaderArena implements Arena { @Override public final void checkReadLimit(int numWords) { if (limit == -1) { + // No limit. return; } else if (numWords > limit) { throw new DecodeException("Read limit exceeded."); diff --git a/runtime/src/main/java/org/capnproto/ReaderOptions.java b/runtime/src/main/java/org/capnproto/ReaderOptions.java index fa22b40..21cee6d 100644 --- a/runtime/src/main/java/org/capnproto/ReaderOptions.java +++ b/runtime/src/main/java/org/capnproto/ReaderOptions.java @@ -22,7 +22,18 @@ package org.capnproto; public final class ReaderOptions { + /** + How many words are allowed to be read before an exception is thrown, + to protect against denial of service attacks. + + -1 means "no limit". + */ public final long traversalLimitInWords; + + /** + How many pointer indirections deep a message may be before an exception + is thrown. + */ public final int nestingLimit; public ReaderOptions(long traversalLimitInWords, int nestingLimit) { From eb73990798758bd08bc9411127a95749df4847dc Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Tue, 11 May 2021 21:03:41 -0400 Subject: [PATCH 04/37] fix potential overflow in DefaultAllocator Fixes a bug where the allocator's `nextSize` variable could overflow and become negative, causing more segments to be allocated than expected. Also removes a duplicate `this.nextSize += size` statement that likely made the problem worse. --- .../java/org/capnproto/DefaultAllocator.java | 18 +++++++++++++-- .../org/capnproto/DefaultAllocatorTest.java | 23 +++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java diff --git a/runtime/src/main/java/org/capnproto/DefaultAllocator.java b/runtime/src/main/java/org/capnproto/DefaultAllocator.java index d136356..1d1d1bb 100644 --- a/runtime/src/main/java/org/capnproto/DefaultAllocator.java +++ b/runtime/src/main/java/org/capnproto/DefaultAllocator.java @@ -18,6 +18,17 @@ public class DefaultAllocator implements Allocator { public AllocationStrategy allocationStrategy = AllocationStrategy.GROW_HEURISTICALLY; + /** + The largest number of bytes to try allocating when using `GROW_HEURISTICALLY`. + + Set this value smaller if you get the error: + + java.lang.OutOfMemoryError: Requested array size exceeds VM limit + + Experimentally, `Integer.MAX_VALUE - 2` seems to work on most systems. + */ + public int maxSegmentBytes = Integer.MAX_VALUE - 2; + public DefaultAllocator() {} public DefaultAllocator(AllocationStrategy allocationStrategy) { @@ -52,13 +63,16 @@ public class DefaultAllocator implements Allocator { switch (this.allocationStrategy) { case GROW_HEURISTICALLY: - this.nextSize += size; + if (size < this.maxSegmentBytes - this.nextSize) { + this.nextSize += size; + } else { + this.nextSize = maxSegmentBytes; + } break; case FIXED_SIZE: break; } - this.nextSize += size; return result; } } diff --git a/runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java b/runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java new file mode 100644 index 0000000..fcd6658 --- /dev/null +++ b/runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java @@ -0,0 +1,23 @@ +package org.capnproto; + +import org.junit.Assert; +import org.junit.Test; + +public class DefaultAllocatorTest { + @Test + public void checkNoOverflow() { + DefaultAllocator allocator = new DefaultAllocator(); + Assert.assertEquals(allocator.allocationStrategy, + BuilderArena.AllocationStrategy.GROW_HEURISTICALLY); + allocator.setNextAllocationSizeBytes(1 << 30); + + Assert.assertEquals(1 << 30, + allocator.allocateSegment(1 << 30).capacity()); + + Assert.assertEquals(allocator.maxSegmentBytes, + allocator.allocateSegment(1 << 30).capacity()); + + Assert.assertEquals(allocator.maxSegmentBytes, + allocator.allocateSegment(1 << 30).capacity()); + } +} From 8dbd5cf25fada85dc413b4744ff6d7dfba1ac6ca Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Tue, 11 May 2021 21:12:10 -0400 Subject: [PATCH 05/37] make new unit test less memory intensive --- .../java/org/capnproto/DefaultAllocatorTest.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java b/runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java index fcd6658..3770a7b 100644 --- a/runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java +++ b/runtime/src/test/java/org/capnproto/DefaultAllocatorTest.java @@ -5,19 +5,22 @@ import org.junit.Test; public class DefaultAllocatorTest { @Test - public void checkNoOverflow() { + public void maxSegmentBytes() { DefaultAllocator allocator = new DefaultAllocator(); Assert.assertEquals(allocator.allocationStrategy, BuilderArena.AllocationStrategy.GROW_HEURISTICALLY); - allocator.setNextAllocationSizeBytes(1 << 30); + allocator.maxSegmentBytes = (1 << 25) - 1; - Assert.assertEquals(1 << 30, - allocator.allocateSegment(1 << 30).capacity()); + int allocationSize = 1 << 24; + allocator.setNextAllocationSizeBytes(allocationSize); + + Assert.assertEquals(allocationSize, + allocator.allocateSegment(allocationSize).capacity()); Assert.assertEquals(allocator.maxSegmentBytes, - allocator.allocateSegment(1 << 30).capacity()); + allocator.allocateSegment(allocationSize).capacity()); Assert.assertEquals(allocator.maxSegmentBytes, - allocator.allocateSegment(1 << 30).capacity()); + allocator.allocateSegment(allocationSize).capacity()); } } From ee7e9a0d07bb53f8511b59d6da3f5eb81d54121c Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Tue, 11 May 2021 21:46:25 -0400 Subject: [PATCH 06/37] publish 0.1.6 --- benchmark/pom.xml | 2 +- compiler/pom.xml | 2 +- examples/pom.xml | 2 +- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 6f2aafd..42e4b5a 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.6-SNAPSHOT + 0.1.6 capnproto-java benchmark org.capnproto diff --git a/compiler/pom.xml b/compiler/pom.xml index afac45e..97c76fd 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.6-SNAPSHOT + 0.1.6 capnpc-java org.capnproto diff --git a/examples/pom.xml b/examples/pom.xml index ff0190f..6e487eb 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.6-SNAPSHOT + 0.1.6 capnproto-java examples org.capnproto diff --git a/pom.xml b/pom.xml index 83fd696..99c9a8e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.6-SNAPSHOT + 0.1.6 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 9f0ab52..a5f181b 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.6-SNAPSHOT + 0.1.6 Cap'n Proto runtime library org.capnproto From a6c52407909191d8aabab83f158a5dbcb286ff45 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Tue, 11 May 2021 21:49:54 -0400 Subject: [PATCH 07/37] bump version numbers to 0.1.7-SNAPSHOT --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 42e4b5a..51824ef 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.6 + 0.1.7-SNAPSHOT capnproto-java benchmark org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.6-SNAPSHOT + 0.1.7-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index 97c76fd..9974ebe 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.6 + 0.1.7-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.6-SNAPSHOT + 0.1.7-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index 6e487eb..a4302e0 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.6 + 0.1.7-SNAPSHOT capnproto-java examples org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.6-SNAPSHOT + 0.1.7-SNAPSHOT diff --git a/pom.xml b/pom.xml index 99c9a8e..75353e3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.6 + 0.1.7-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index a5f181b..958de07 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.6 + 0.1.7-SNAPSHOT Cap'n Proto runtime library org.capnproto From 4ec14e39f98aeda5d513923ad7d5be7618b2e8aa Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 12 May 2021 20:13:52 -0400 Subject: [PATCH 08/37] be more careful about integer overflow in Serialize.read() Previously, we were attempting to read the entire message in one call to fillBuffer(). This was doomed to fail if the message had more than Integer.MAX_VALUE bytes. After this diff, we will call fillBuffer() separately for each segment. This approach turns out to be simpler, too. It might imply a small performance hit for messages with many small segments, but such messages are discouraged anyway. This diff also adds more overflow checking in the surrounding logic. --- .../main/java/org/capnproto/Serialize.java | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/runtime/src/main/java/org/capnproto/Serialize.java b/runtime/src/main/java/org/capnproto/Serialize.java index 4d9aeaa..34212d0 100644 --- a/runtime/src/main/java/org/capnproto/Serialize.java +++ b/runtime/src/main/java/org/capnproto/Serialize.java @@ -37,6 +37,16 @@ public final class Serialize { return result; } + static int MAX_SEGMENT_WORDS = (1 << 28) - 1; + + static ByteBuffer makeByteBufferForWords(int words) throws IOException { + if (words > MAX_SEGMENT_WORDS) { + // Trying to construct the segment would cause overflow. + throw new DecodeException("segment has too many words (" + words + ")"); + } + return makeByteBuffer(words * Constants.BYTES_PER_WORD); + } + public static void fillBuffer(ByteBuffer buffer, ReadableByteChannel bc) throws IOException { while(buffer.hasRemaining()) { int r = bc.read(buffer); @@ -53,21 +63,22 @@ public final class Serialize { } public static MessageReader read(ReadableByteChannel bc, ReaderOptions options) throws IOException { - ByteBuffer firstWord = makeByteBuffer(Constants.BYTES_PER_WORD); + ByteBuffer firstWord = makeByteBufferForWords(1); fillBuffer(firstWord, bc); - int segmentCount = 1 + firstWord.getInt(0); + int rawSegmentCount = firstWord.getInt(0); + if (rawSegmentCount < 0 || rawSegmentCount > 511) { + throw new DecodeException("segment count must be between 0 and 512"); + } + + int segmentCount = 1 + rawSegmentCount; int segment0Size = 0; if (segmentCount > 0) { segment0Size = firstWord.getInt(4); } - int totalWords = segment0Size; - - if (segmentCount > 512) { - throw new IOException("too many segments"); - } + long totalWords = segment0Size; // in words ArrayList moreSizes = new ArrayList(); @@ -86,23 +97,17 @@ public final class Serialize { throw new DecodeException("Message size exceeds traversal limit."); } - ByteBuffer allSegments = makeByteBuffer(totalWords * Constants.BYTES_PER_WORD); - fillBuffer(allSegments, bc); - ByteBuffer[] segmentSlices = new ByteBuffer[segmentCount]; - allSegments.rewind(); - segmentSlices[0] = allSegments.slice(); - segmentSlices[0].limit(segment0Size * Constants.BYTES_PER_WORD); - segmentSlices[0].order(ByteOrder.LITTLE_ENDIAN); + segmentSlices[0] = makeByteBufferForWords(segment0Size); + fillBuffer(segmentSlices[0], bc); + segmentSlices[0].rewind(); int offset = segment0Size; for (int ii = 1; ii < segmentCount; ++ii) { - allSegments.position(offset * Constants.BYTES_PER_WORD); - segmentSlices[ii] = allSegments.slice(); - segmentSlices[ii].limit(moreSizes.get(ii - 1) * Constants.BYTES_PER_WORD); - segmentSlices[ii].order(ByteOrder.LITTLE_ENDIAN); - offset += moreSizes.get(ii - 1); + segmentSlices[ii] = makeByteBufferForWords(moreSizes.get(ii - 1)); + fillBuffer(segmentSlices[ii], bc); + segmentSlices[ii].rewind(); } return new MessageReader(segmentSlices, options); @@ -112,15 +117,16 @@ public final class Serialize { return read(bb, ReaderOptions.DEFAULT_READER_OPTIONS); } - /* + /** * Upon return, `bb.position()` will be at the end of the message. */ public static MessageReader read(ByteBuffer bb, ReaderOptions options) throws IOException { bb.order(ByteOrder.LITTLE_ENDIAN); - int segmentCount = 1 + bb.getInt(); - if (segmentCount > 512) { - throw new IOException("too many segments"); + int rawSegmentCount = bb.getInt(); + int segmentCount = 1 + rawSegmentCount; + if (rawSegmentCount < 0 || rawSegmentCount > 511) { + throw new DecodeException("segment count must be between 0 and 512"); } ByteBuffer[] segmentSlices = new ByteBuffer[segmentCount]; @@ -135,6 +141,10 @@ public final class Serialize { for (int ii = 0; ii < segmentCount; ++ii) { int segmentSize = bb.getInt(segmentSizesBase + ii * 4); + if (segmentSize > MAX_SEGMENT_WORDS - + (totalWords + segmentBase / Constants.BYTES_PER_WORD)) { + throw new DecodeException("segment size is too large"); + } bb.position(segmentBase + totalWords * Constants.BYTES_PER_WORD); segmentSlices[ii] = bb.slice(); From 5bf2c368e31d424fbf2be329dde6325792f4fec3 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 12 May 2021 20:57:00 -0400 Subject: [PATCH 09/37] 0.1.7 release --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 51824ef..68952ce 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.7-SNAPSHOT + 0.1.7 capnproto-java benchmark org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.7-SNAPSHOT + 0.1.7 diff --git a/compiler/pom.xml b/compiler/pom.xml index 9974ebe..e7f9e4c 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.7-SNAPSHOT + 0.1.7 capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.7-SNAPSHOT + 0.1.7 diff --git a/examples/pom.xml b/examples/pom.xml index a4302e0..09fa521 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.7-SNAPSHOT + 0.1.7 capnproto-java examples org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.7-SNAPSHOT + 0.1.7 diff --git a/pom.xml b/pom.xml index 75353e3..b32cbc9 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.7-SNAPSHOT + 0.1.7 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 958de07..204e291 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.7-SNAPSHOT + 0.1.7 Cap'n Proto runtime library org.capnproto From 754184fd74fc0ef0801a1d7fbdc08775461cfec4 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 12 May 2021 21:00:16 -0400 Subject: [PATCH 10/37] bump version numbers to 0.1.8-SNAPSHOT --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 68952ce..80c96d6 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.7 + 0.1.8-SNAPSHOT capnproto-java benchmark org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.7 + 0.1.8-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index e7f9e4c..35184ea 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.7 + 0.1.8-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.7 + 0.1.8-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index 09fa521..b2da9d1 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.7 + 0.1.8-SNAPSHOT capnproto-java examples org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.7 + 0.1.8-SNAPSHOT diff --git a/pom.xml b/pom.xml index b32cbc9..d19acb7 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.7 + 0.1.8-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 204e291..923ee02 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.7 + 0.1.8-SNAPSHOT Cap'n Proto runtime library org.capnproto From d310db1e8895cbc4d65d5e7cfef7cdcbfa21edd1 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Thu, 13 May 2021 17:49:01 -0400 Subject: [PATCH 11/37] Prevent potential integer overflow in BuilderArena.allocate(). --- runtime/src/main/java/org/capnproto/BuilderArena.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runtime/src/main/java/org/capnproto/BuilderArena.java b/runtime/src/main/java/org/capnproto/BuilderArena.java index 37dc774..0323fad 100644 --- a/runtime/src/main/java/org/capnproto/BuilderArena.java +++ b/runtime/src/main/java/org/capnproto/BuilderArena.java @@ -87,6 +87,10 @@ public final class BuilderArena implements Arena { } } + /** + * Allocates `amount` words in an existing segment or, if no suitable segment + * exists, in a new segment. + */ public AllocateResult allocate(int amount) { int len = this.segments.size(); @@ -97,6 +101,10 @@ public final class BuilderArena implements Arena { return new AllocateResult(this.segments.get(len - 1), result); } } + if (amount >= 1 << 28) { + // Computing `amount * Constants.BYTES_PER_WORD` would overflow. + throw new RuntimeException("Too many words to allocate: " + amount); + } SegmentBuilder newSegment = new SegmentBuilder( this.allocator.allocateSegment(amount * Constants.BYTES_PER_WORD), this); From a078df7e4d8789cb04765fbfd79103808fd5eac7 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 24 May 2021 11:49:20 -0400 Subject: [PATCH 12/37] add support for directly serializing a MessageReader Previously, you would need to copy the message into a MessageBuilder first. --- .../main/java/org/capnproto/Serialize.java | 37 +++++++++++++++++-- .../java/org/capnproto/SerializePacked.java | 29 +++++++++++++++ .../java/org/capnproto/SerializeTest.java | 4 ++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/runtime/src/main/java/org/capnproto/Serialize.java b/runtime/src/main/java/org/capnproto/Serialize.java index 34212d0..5e7a7f4 100644 --- a/runtime/src/main/java/org/capnproto/Serialize.java +++ b/runtime/src/main/java/org/capnproto/Serialize.java @@ -28,6 +28,10 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; +/** + * Serialization using the standard (unpacked) stream encoding: + * https://capnproto.org/encoding.html#serialization-over-a-stream + */ public final class Serialize { static ByteBuffer makeByteBuffer(int bytes) { @@ -186,9 +190,8 @@ public final class Serialize { return bytes / Constants.BYTES_PER_WORD; } - public static void write(WritableByteChannel outputChannel, - MessageBuilder message) throws IOException { - ByteBuffer[] segments = message.getSegmentsForOutput(); + private static void writeSegmentTable(WritableByteChannel outputChannel, + ByteBuffer[] segments) throws IOException { int tableSize = (segments.length + 2) & (~1); ByteBuffer table = ByteBuffer.allocate(4 * tableSize); @@ -204,6 +207,34 @@ public final class Serialize { while (table.hasRemaining()) { outputChannel.write(table); } + } + + /** + * Serializes a MessageBuilder to a WritableByteChannel. + */ + public static void write(WritableByteChannel outputChannel, + MessageBuilder message) throws IOException { + ByteBuffer[] segments = message.getSegmentsForOutput(); + writeSegmentTable(outputChannel, segments); + + for (ByteBuffer buffer : segments) { + while(buffer.hasRemaining()) { + outputChannel.write(buffer); + } + } + } + + /** + * Serializes a MessageReader to a WritableByteChannel. + */ + public static void write(WritableByteChannel outputChannel, + MessageReader message) throws IOException { + ByteBuffer[] segments = new ByteBuffer[message.arena.segments.size()]; + for (int ii = 0 ; ii < message.arena.segments.size(); ++ii) { + segments[ii] = message.arena.segments.get(ii).buffer.duplicate(); + } + + writeSegmentTable(outputChannel, segments); for (ByteBuffer buffer : segments) { while(buffer.hasRemaining()) { diff --git a/runtime/src/main/java/org/capnproto/SerializePacked.java b/runtime/src/main/java/org/capnproto/SerializePacked.java index 1a107eb..88b31a9 100644 --- a/runtime/src/main/java/org/capnproto/SerializePacked.java +++ b/runtime/src/main/java/org/capnproto/SerializePacked.java @@ -21,6 +21,9 @@ package org.capnproto; +/** + * Serialization using the packed encoding: https://capnproto.org/encoding.html#packing + */ public final class SerializePacked { public static MessageReader read(BufferedInputStream input) throws java.io.IOException { @@ -42,16 +45,42 @@ public final class SerializePacked { return Serialize.read(packedInput, options); } + /** + * Serializes a MessageBuilder to a BufferedOutputStream. + */ public static void write(BufferedOutputStream output, MessageBuilder message) throws java.io.IOException { PackedOutputStream packedOutputStream = new PackedOutputStream(output); Serialize.write(packedOutputStream, message); } + /** + * Serializes a MessageReader to a BufferedOutputStream. + */ + public static void write(BufferedOutputStream output, + MessageReader message) throws java.io.IOException { + PackedOutputStream packedOutputStream = new PackedOutputStream(output); + Serialize.write(packedOutputStream, message); + } + + /** + * Serializes a MessageBuilder to an unbuffered output stream. + */ public static void writeToUnbuffered(java.nio.channels.WritableByteChannel output, MessageBuilder message) throws java.io.IOException { BufferedOutputStreamWrapper buffered = new BufferedOutputStreamWrapper(output); write(buffered, message); buffered.flush(); } + + /** + * Serializes a MessageReader to an unbuffered output stream. + */ + public static void writeToUnbuffered(java.nio.channels.WritableByteChannel output, + MessageReader message) throws java.io.IOException { + BufferedOutputStreamWrapper buffered = new BufferedOutputStreamWrapper(output); + write(buffered, message); + buffered.flush(); + } + } diff --git a/runtime/src/test/java/org/capnproto/SerializeTest.java b/runtime/src/test/java/org/capnproto/SerializeTest.java index 5b5c5f4..b83cb85 100644 --- a/runtime/src/test/java/org/capnproto/SerializeTest.java +++ b/runtime/src/test/java/org/capnproto/SerializeTest.java @@ -55,6 +55,10 @@ public class SerializeTest { { MessageReader messageReader = Serialize.read(new ArrayInputStream(ByteBuffer.wrap(exampleBytes))); checkSegmentContents(exampleSegmentCount, messageReader.arena); + + byte[] outputBytes = new byte[exampleBytes.length]; + Serialize.write(new ArrayOutputStream(ByteBuffer.wrap(outputBytes)), messageReader); + Assert.assertArrayEquals(exampleBytes, outputBytes); } // ------ From a55b869305f74e87010c17ec77ad2e36c2c6b0d2 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 24 May 2021 13:06:42 -0400 Subject: [PATCH 13/37] implement MessageBuilder.unsafeConstructFromMessageReader() --- .../main/java/org/capnproto/BuilderArena.java | 24 +++++++++++++++++++ .../java/org/capnproto/MessageBuilder.java | 16 +++++++++++++ .../java/org/capnproto/SegmentBuilder.java | 2 +- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/runtime/src/main/java/org/capnproto/BuilderArena.java b/runtime/src/main/java/org/capnproto/BuilderArena.java index 0323fad..02d4396 100644 --- a/runtime/src/main/java/org/capnproto/BuilderArena.java +++ b/runtime/src/main/java/org/capnproto/BuilderArena.java @@ -64,6 +64,30 @@ public final class BuilderArena implements Arena { this.allocator = allocator; } + /** + * Constructs a BuilderArena from a ReaderArena and uses the size of the largest segment + * as the next allocation size. + */ + BuilderArena(ReaderArena arena) { + this.segments = new ArrayList(); + int largestSegment = SUGGESTED_FIRST_SEGMENT_WORDS*Constants.BYTES_PER_WORD; + for (int ii = 0; ii < arena.segments.size(); ++ii) { + SegmentReader segment = arena.segments.get(ii); + SegmentBuilder segmentBuilder = new SegmentBuilder(segment.buffer, this); + segmentBuilder.id = ii; + segmentBuilder.pos = segmentBuilder.capacity(); // buffer is pre-filled + segments.add(segmentBuilder); + + // Find the largest segment for the allocation strategy. + largestSegment = Math.max(largestSegment, segment.buffer.capacity()); + } + DefaultAllocator defaultAllocator = new DefaultAllocator(SUGGESTED_ALLOCATION_STRATEGY); + + // Use largest segment as next size. + defaultAllocator.setNextAllocationSizeBytes(largestSegment); + this.allocator = defaultAllocator; + } + @Override public final SegmentReader tryGetSegment(int id) { return this.segments.get(id); diff --git a/runtime/src/main/java/org/capnproto/MessageBuilder.java b/runtime/src/main/java/org/capnproto/MessageBuilder.java index 40d714d..8d75b6d 100644 --- a/runtime/src/main/java/org/capnproto/MessageBuilder.java +++ b/runtime/src/main/java/org/capnproto/MessageBuilder.java @@ -71,6 +71,22 @@ public final class MessageBuilder { this.arena = new BuilderArena(new DefaultAllocator(), firstSegment); } + /** + * Constructs a MessageBuilder from a MessageReader. This constructor is private + * because it is unsafe. To use it, you must call `unsafeConstructFromMessageReader()`. + */ + private MessageBuilder(MessageReader messageReader) { + this.arena = new BuilderArena(messageReader.arena); + } + + /** + * Constructs a MessageBuilder from a MessageReader without copying the segments. + * This method should only be used on trusted data. Otherwise you may observe infinite + * loops or large memory allocations or index-out-of-bounds errors. + */ + public static MessageBuilder unsafeConstructFromMessageReader(MessageReader messageReader) { + return new MessageBuilder(messageReader); + } private AnyPointer.Builder getRootInternal() { if (this.arena.segments.isEmpty()) { diff --git a/runtime/src/main/java/org/capnproto/SegmentBuilder.java b/runtime/src/main/java/org/capnproto/SegmentBuilder.java index e9ac57a..9727b58 100644 --- a/runtime/src/main/java/org/capnproto/SegmentBuilder.java +++ b/runtime/src/main/java/org/capnproto/SegmentBuilder.java @@ -35,7 +35,7 @@ public final class SegmentBuilder extends SegmentReader { } // the total number of words the buffer can hold - private final int capacity() { + final int capacity() { this.buffer.rewind(); return this.buffer.remaining() / 8; } From 01cf6c0ebf0b2e380208a965098819bb2e589f22 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 31 May 2021 08:33:52 -0400 Subject: [PATCH 14/37] release v0.1.8 --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 80c96d6..65a7ae3 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.8-SNAPSHOT + 0.1.8 capnproto-java benchmark org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.8-SNAPSHOT + 0.1.8 diff --git a/compiler/pom.xml b/compiler/pom.xml index 35184ea..c4a36f4 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.8-SNAPSHOT + 0.1.8 capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.8-SNAPSHOT + 0.1.8 diff --git a/examples/pom.xml b/examples/pom.xml index b2da9d1..de1a5c2 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.8-SNAPSHOT + 0.1.8 capnproto-java examples org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.8-SNAPSHOT + 0.1.8 diff --git a/pom.xml b/pom.xml index d19acb7..51552d2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.8-SNAPSHOT + 0.1.8 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 923ee02..37f2d7f 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.8-SNAPSHOT + 0.1.8 Cap'n Proto runtime library org.capnproto From f98e0fc6efe67c3593215289f27959540cb6feba Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 31 May 2021 08:45:24 -0400 Subject: [PATCH 15/37] bump version to 0.1.9-SNAPSHOT --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 65a7ae3..18192a7 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.8 + 0.1.9-SNAPSHOT capnproto-java benchmark org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.8 + 0.1.9-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index c4a36f4..f18b173 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.8 + 0.1.9-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.8 + 0.1.9-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index de1a5c2..899c8fb 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.8 + 0.1.9-SNAPSHOT capnproto-java examples org.capnproto @@ -38,7 +38,7 @@ org.capnproto runtime - 0.1.8 + 0.1.9-SNAPSHOT diff --git a/pom.xml b/pom.xml index 51552d2..40faafa 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.8 + 0.1.9-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 37f2d7f..93362f7 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.8 + 0.1.9-SNAPSHOT Cap'n Proto runtime library org.capnproto From b8a5a99ef649e70968350b7355407487f8c5a487 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Wed, 14 Jul 2021 15:41:56 -0400 Subject: [PATCH 16/37] try adding maven.compiler.release flag (#104) --- benchmark/pom.xml | 1 + examples/pom.xml | 1 + runtime/pom.xml | 1 + 3 files changed, 3 insertions(+) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 18192a7..ea0f3e9 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -33,6 +33,7 @@ UTF-8 1.8 1.8 + 8 diff --git a/examples/pom.xml b/examples/pom.xml index 899c8fb..868d27b 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -33,6 +33,7 @@ UTF-8 1.8 1.8 + 8 diff --git a/runtime/pom.xml b/runtime/pom.xml index 93362f7..678d3a7 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -33,6 +33,7 @@ UTF-8 1.8 1.8 + 8 From 80f5b0447aadd0b1542f6678cb962b57967e3456 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 16 Jul 2021 11:10:45 -0400 Subject: [PATCH 17/37] prepare for 0.1.9 release --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index ea0f3e9..3293d87 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.9-SNAPSHOT + 0.1.9 capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.9-SNAPSHOT + 0.1.9 diff --git a/compiler/pom.xml b/compiler/pom.xml index f18b173..b3bc233 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.9-SNAPSHOT + 0.1.9 capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.9-SNAPSHOT + 0.1.9 diff --git a/examples/pom.xml b/examples/pom.xml index 868d27b..0630ea8 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.9-SNAPSHOT + 0.1.9 capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.9-SNAPSHOT + 0.1.9 diff --git a/pom.xml b/pom.xml index 40faafa..103dd50 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.9-SNAPSHOT + 0.1.9 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 678d3a7..a39d3b5 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.9-SNAPSHOT + 0.1.9 Cap'n Proto runtime library org.capnproto From 1966572eca001d796afa1641e472149c23519066 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 16 Jul 2021 11:38:03 -0400 Subject: [PATCH 18/37] update version numbers to 0.1.10-SNAPSHOT --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 3293d87..ef7733d 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.9 + 0.1.10-SNAPSHOT capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.9 + 0.1.10-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index b3bc233..cf983b9 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.9 + 0.1.10-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.9 + 0.1.10-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index 0630ea8..ef967e2 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.9 + 0.1.10-SNAPSHOT capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.9 + 0.1.10-SNAPSHOT diff --git a/pom.xml b/pom.xml index 103dd50..90445ff 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.9 + 0.1.10-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index a39d3b5..1d79a63 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.9 + 0.1.10-SNAPSHOT Cap'n Proto runtime library org.capnproto From cd3ef7216635943756ce636fc03aabd4d27a1c05 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 16 Jul 2021 14:20:29 -0400 Subject: [PATCH 19/37] add changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a42245c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +## v0.1.9 +- Add `8` to pom.xml, to increase compability with Java 8. From a36bf2e6bdd5d8fc5876e54b6e12f39b43bd042a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Jeli=C5=84ski?= <59468166+ajelinski@users.noreply.github.com> Date: Wed, 18 Aug 2021 14:12:21 +0200 Subject: [PATCH 20/37] Makefile: Enable overriding `pkg-config` (#107) Sometimes there's a need to precise which `pkg-config` is to be used. Now `pkg-config`'s name or path can be overridden with `PKG_CONFIG`. Fixes #106. --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4882d9c..493539b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ -CAPNP_CXX_FLAGS=$(shell pkg-config capnp --cflags --libs) +PKG_CONFIG ?= pkg-config +CAPNP_CXX_FLAGS=$(shell $(PKG_CONFIG) capnp --cflags --libs) ifeq ($(CAPNP_CXX_FLAGS),) $(warning "Warning: pkg-config failed to find compilation configuration for capnp.") From 9e114cf26df70befab328d63dc375d0bde79f587 Mon Sep 17 00:00:00 2001 From: paxel Date: Wed, 18 Aug 2021 16:02:33 +0200 Subject: [PATCH 21/37] made runtime build for JDK8 under all JDKs (8++) (#109) * Update pom.xml made runtime build for JDK8 under all JDKs (8++) * Update runtime/pom.xml use more-standard syntax Co-authored-by: David Renshaw --- runtime/pom.xml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/runtime/pom.xml b/runtime/pom.xml index 1d79a63..f162b4d 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -33,7 +33,6 @@ UTF-8 1.8 1.8 - 8 @@ -60,7 +59,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.3 + 3.6.2 -Xlint:unchecked @@ -69,6 +68,15 @@ + + jdk9FF + + (1.8,) + + + 8 + + release From b1a197be75b00c6d9d6d582569cefd9cebffcb5a Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 27 Aug 2021 21:13:49 -0400 Subject: [PATCH 22/37] prepare for 0.1.10 release --- CHANGELOG.md | 3 +++ benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a42245c..bdd1657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,5 @@ +## v0.1.10 +- Make even more compatible with Java 8. + ## v0.1.9 - Add `8` to pom.xml, to increase compability with Java 8. diff --git a/benchmark/pom.xml b/benchmark/pom.xml index ef7733d..1b26f1a 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.10-SNAPSHOT + 0.1.10 capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.10-SNAPSHOT + 0.1.10 diff --git a/compiler/pom.xml b/compiler/pom.xml index cf983b9..4a3e0c8 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.10-SNAPSHOT + 0.1.10 capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.10-SNAPSHOT + 0.1.10 diff --git a/examples/pom.xml b/examples/pom.xml index ef967e2..7e41c39 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.10-SNAPSHOT + 0.1.10 capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.10-SNAPSHOT + 0.1.10 diff --git a/pom.xml b/pom.xml index 90445ff..61873fa 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.10-SNAPSHOT + 0.1.10 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index f162b4d..70b6b68 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.10-SNAPSHOT + 0.1.10 Cap'n Proto runtime library org.capnproto From f3e66a6e0b69b8d961dfb017e299683591770b60 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 27 Aug 2021 21:23:00 -0400 Subject: [PATCH 23/37] update versions to 0.1.11-SNAPSHOT --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 1b26f1a..5b7085a 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.10 + 0.1.11-SNAPSHOT capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.10 + 0.1.11-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index 4a3e0c8..780efd6 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.10 + 0.1.11-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.10 + 0.1.11-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index 7e41c39..3064411 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.10 + 0.1.11-SNAPSHOT capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.10 + 0.1.11-SNAPSHOT diff --git a/pom.xml b/pom.xml index 61873fa..8b00046 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.10 + 0.1.11-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 70b6b68..a031dc3 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.10 + 0.1.11-SNAPSHOT Cap'n Proto runtime library org.capnproto From ddd43a491b333848ffebc7e05d854ca70c49cf6d Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Thu, 30 Sep 2021 18:26:33 -0400 Subject: [PATCH 24/37] throw exception on negative segment sizes --- .../src/main/java/org/capnproto/Serialize.java | 9 +++++++++ .../test/java/org/capnproto/SerializeTest.java | 18 ++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/runtime/src/main/java/org/capnproto/Serialize.java b/runtime/src/main/java/org/capnproto/Serialize.java index 5e7a7f4..c8720be 100644 --- a/runtime/src/main/java/org/capnproto/Serialize.java +++ b/runtime/src/main/java/org/capnproto/Serialize.java @@ -82,6 +82,10 @@ public final class Serialize { segment0Size = firstWord.getInt(4); } + if (segment0Size < 0) { + throw new DecodeException("segment 0 has more than 2^31 words, which is unsupported"); + } + long totalWords = segment0Size; // in words @@ -92,6 +96,11 @@ public final class Serialize { fillBuffer(moreSizesRaw, bc); for (int ii = 0; ii < segmentCount - 1; ++ii) { int size = moreSizesRaw.getInt(ii * 4); + if (size < 0) { + throw new DecodeException("segment " + (ii + 1) + + " has more than 2^31 words, which is unsupported"); + } + moreSizes.add(size); totalWords += size; } diff --git a/runtime/src/test/java/org/capnproto/SerializeTest.java b/runtime/src/test/java/org/capnproto/SerializeTest.java index b83cb85..3fdcc0a 100644 --- a/runtime/src/test/java/org/capnproto/SerializeTest.java +++ b/runtime/src/test/java/org/capnproto/SerializeTest.java @@ -129,4 +129,22 @@ public class SerializeTest { 3, 0, 0, 0, 0, 0, 0, 0 }); } + + @Test(expected=DecodeException.class) + public void testSegment0SizeOverflow() throws java.io.IOException { + byte[] input = {0, 0, 0, 0, -1, -1, -1, -113}; + java.nio.channels.ReadableByteChannel channel = + java.nio.channels.Channels.newChannel(new java.io.ByteArrayInputStream(input)); + MessageReader message = Serialize.read(channel); + } + + @Test(expected=DecodeException.class) + public void testSegment1SizeOverflow() throws java.io.IOException { + byte[] input = { + 1, 0, 0, 0, 1, 0, 0, 0, + -1, -1, -1, -113, 0, 0, 0, 0}; + java.nio.channels.ReadableByteChannel channel = + java.nio.channels.Channels.newChannel(new java.io.ByteArrayInputStream(input)); + MessageReader message = Serialize.read(channel); + } } From 104fb11104d37bbd055f0a9bfcc25d19ddbb7698 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 1 Oct 2021 21:11:33 -0400 Subject: [PATCH 25/37] add bounds checking in readListPointer --- .../java/org/capnproto/test/EncodingTest.java | 18 ++++++++++++++++++ .../java/org/capnproto/SegmentReader.java | 8 ++++++++ .../main/java/org/capnproto/WireHelpers.java | 19 +++++++++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/compiler/src/test/java/org/capnproto/test/EncodingTest.java b/compiler/src/test/java/org/capnproto/test/EncodingTest.java index 1f10853..f52afd4 100644 --- a/compiler/src/test/java/org/capnproto/test/EncodingTest.java +++ b/compiler/src/test/java/org/capnproto/test/EncodingTest.java @@ -614,6 +614,24 @@ public class EncodingTest { root.getAnyPointerField().getAs(StructList.newFactory(Test.TestAllTypes.factory)); } + // Test that we throw an exception on out-of-bounds list pointers. + // Before v0.1.11, we were vulnerable to a cpu amplification attack: + // reading an out-of-bounds pointer to list a huge number of elements of size BIT, + // when read as a struct list, would return without error. + @org.junit.Test(expected=DecodeException.class) + public void testListPointerOutOfBounds() throws DecodeException { + byte[] bytes = new byte[] + {0,0,0,0, 0,0,1,0, // struct, one pointer + 1, 0x2f, 0, 0, 1, 0, -127, -128}; // list, points out of bounds. + ByteBuffer segment = ByteBuffer.wrap(bytes); + segment.order(ByteOrder.LITTLE_ENDIAN); + MessageReader message = new MessageReader(new ByteBuffer[]{segment}, + ReaderOptions.DEFAULT_READER_OPTIONS); + + Test.TestAnyPointer.Reader root = message.getRoot(Test.TestAnyPointer.factory); + root.getAnyPointerField().getAs(StructList.newFactory(Test.TestAllTypes.factory)); + } + @org.junit.Test public void testLongUint8List() { MessageBuilder message = new MessageBuilder(); diff --git a/runtime/src/main/java/org/capnproto/SegmentReader.java b/runtime/src/main/java/org/capnproto/SegmentReader.java index 82f8330..b407d21 100644 --- a/runtime/src/main/java/org/capnproto/SegmentReader.java +++ b/runtime/src/main/java/org/capnproto/SegmentReader.java @@ -38,4 +38,12 @@ public class SegmentReader { public final long get(int index) { return buffer.getLong(index * Constants.BYTES_PER_WORD); } + + // Verify that the `size`-long (in words) range starting at word index + // `start` is within bounds. + public final boolean in_bounds(int start, int size) { + if (start < 0 || size < 0) return false; + long sizeInWords = size * Constants.BYTES_PER_WORD; + return (long) start + sizeInWords < (long) this.buffer.capacity(); + } } diff --git a/runtime/src/main/java/org/capnproto/WireHelpers.java b/runtime/src/main/java/org/capnproto/WireHelpers.java index 2c9da87..64e6fff 100644 --- a/runtime/src/main/java/org/capnproto/WireHelpers.java +++ b/runtime/src/main/java/org/capnproto/WireHelpers.java @@ -38,6 +38,14 @@ final class WireHelpers { return (int)((bits + 63) / ((long) Constants.BITS_PER_WORD)); } + // ByteBuffer already does bounds checking, but we still want + // to check bounds in some places to avoid cpu amplification attacks. + static boolean bounds_check(SegmentReader segment, + int start, + int size) { + return segment == null || segment.in_bounds(start, size); + } + static class AllocateResult { public final int ptr; public final int refOffset; @@ -1166,6 +1174,9 @@ final class WireHelpers { int ptr = resolved.ptr + 1; resolved.segment.arena.checkReadLimit(wordCount + 1); + if (!bounds_check(resolved.segment, resolved.ptr, wordCount + 1)) { + throw new DecodeException("Message contains out-of-bounds list pointer"); + } int size = WirePointer.inlineCompositeListElementCount(tag); @@ -1201,8 +1212,12 @@ final class WireHelpers { int elementCount = ListPointer.elementCount(resolved.ref); int step = dataSize + pointerCount * Constants.BITS_PER_POINTER; - resolved.segment.arena.checkReadLimit( - roundBitsUpToWords(elementCount * step)); + int wordCount = roundBitsUpToWords((long)elementCount * step); + resolved.segment.arena.checkReadLimit(wordCount); + + if (!bounds_check(resolved.segment, resolved.ptr, wordCount)) { + throw new DecodeException("Message contains out-of-bounds list pointer"); + } if (elementSize == ElementSize.VOID) { // Watch out for lists of void, which can claim to be arbitrarily large without From 8f5f200858e85f9690685100da81a86c6c089418 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Thu, 30 Sep 2021 22:52:00 -0400 Subject: [PATCH 26/37] verify that a list pointer has the correct kind --- runtime/src/main/java/org/capnproto/WireHelpers.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/runtime/src/main/java/org/capnproto/WireHelpers.java b/runtime/src/main/java/org/capnproto/WireHelpers.java index 64e6fff..4a57a89 100644 --- a/runtime/src/main/java/org/capnproto/WireHelpers.java +++ b/runtime/src/main/java/org/capnproto/WireHelpers.java @@ -1165,6 +1165,10 @@ final class WireHelpers { FollowFarsResult resolved = followFars(ref, refTarget, segment); + if (WirePointer.kind(resolved.ref) != WirePointer.LIST) { + throw new DecodeException("Message contains non-list pointer where list was expected."); + } + byte elementSize = ListPointer.elementSize(resolved.ref); switch (elementSize) { case ElementSize.INLINE_COMPOSITE : { From 2efe917ffc4ac14a5b1b70b44f8cf2832988715f Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 1 Oct 2021 22:03:53 -0400 Subject: [PATCH 27/37] prepare for v0.1.11 release --- CHANGELOG.md | 3 +++ benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdd1657..4001a88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.1.11 +- Fix memory and cpu amplification vulnerabilities found by Martin Dindoffer. + ## v0.1.10 - Make even more compatible with Java 8. diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 5b7085a..2010f91 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.11-SNAPSHOT + 0.1.11 capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.11-SNAPSHOT + 0.1.11 diff --git a/compiler/pom.xml b/compiler/pom.xml index 780efd6..2d0b74c 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.11-SNAPSHOT + 0.1.11 capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.11-SNAPSHOT + 0.1.11 diff --git a/examples/pom.xml b/examples/pom.xml index 3064411..8c2a8e8 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.11-SNAPSHOT + 0.1.11 capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.11-SNAPSHOT + 0.1.11 diff --git a/pom.xml b/pom.xml index 8b00046..1cd9ceb 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.11-SNAPSHOT + 0.1.11 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index a031dc3..4ebb663 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.11-SNAPSHOT + 0.1.11 Cap'n Proto runtime library org.capnproto From c1cb55e277c94385f9468d0ab50cab7f8f57623b Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 1 Oct 2021 22:16:17 -0400 Subject: [PATCH 28/37] bump to v0.1.12-SNAPSHOST --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 2010f91..cf9c930 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.11 + 0.1.12-SNAPSHOT capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.11 + 0.1.12-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index 2d0b74c..86510ed 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.11 + 0.1.12-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.11 + 0.1.12-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index 8c2a8e8..f3ae0a5 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.11 + 0.1.12-SNAPSHOT capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.11 + 0.1.12-SNAPSHOT diff --git a/pom.xml b/pom.xml index 1cd9ceb..e864e9b 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.11 + 0.1.12-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 4ebb663..36029e6 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.11 + 0.1.12-SNAPSHOT Cap'n Proto runtime library org.capnproto From 57dec34d2cc734e4a21231ab22063d5ca961ae23 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Tue, 5 Oct 2021 17:03:57 -0400 Subject: [PATCH 29/37] fix bug in short to int conversion in StructPointer --- .../java/org/capnproto/StructPointer.java | 2 +- .../java/org/capnproto/StructPointerTest.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 runtime/src/test/java/org/capnproto/StructPointerTest.java diff --git a/runtime/src/main/java/org/capnproto/StructPointer.java b/runtime/src/main/java/org/capnproto/StructPointer.java index 582e6eb..75d9930 100644 --- a/runtime/src/main/java/org/capnproto/StructPointer.java +++ b/runtime/src/main/java/org/capnproto/StructPointer.java @@ -34,7 +34,7 @@ final class StructPointer{ } public static int wordSize(long ref) { - return (int)dataSize(ref) + (int)ptrCount(ref); + return Short.toUnsignedInt(dataSize(ref)) + Short.toUnsignedInt(ptrCount(ref)); } public static void setFromStructSize(ByteBuffer buffer, int offset, StructSize size) { diff --git a/runtime/src/test/java/org/capnproto/StructPointerTest.java b/runtime/src/test/java/org/capnproto/StructPointerTest.java new file mode 100644 index 0000000..d1a3af3 --- /dev/null +++ b/runtime/src/test/java/org/capnproto/StructPointerTest.java @@ -0,0 +1,21 @@ +package org.capnproto; + +import org.junit.Assert; +import org.junit.Test; + +public class StructPointerTest { + + @Test + public void testWordSize() { + Assert.assertEquals( + 3, + StructPointer.wordSize(0x0001000200000000L)); + } + + @Test + public void testWordSizeUnderflow() { + Assert.assertEquals( + 0x1fffe, + StructPointer.wordSize(0xffffffff00000000L)); + } +} From 335f56f73b95e668cda48d7aa8f5d20264950a20 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Tue, 5 Oct 2021 17:07:23 -0400 Subject: [PATCH 30/37] prepare for v0.1.12 release --- CHANGELOG.md | 3 +++ benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4001a88..4f61308 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.1.12 +- Fix bug in StructPointer.wordSize() found by Martin Dindoffer. + ## v0.1.11 - Fix memory and cpu amplification vulnerabilities found by Martin Dindoffer. diff --git a/benchmark/pom.xml b/benchmark/pom.xml index cf9c930..c5712f6 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.12-SNAPSHOT + 0.1.12 capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.12-SNAPSHOT + 0.1.12 diff --git a/compiler/pom.xml b/compiler/pom.xml index 86510ed..2f5052b 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.12-SNAPSHOT + 0.1.12 capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.12-SNAPSHOT + 0.1.12 diff --git a/examples/pom.xml b/examples/pom.xml index f3ae0a5..310db14 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.12-SNAPSHOT + 0.1.12 capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.12-SNAPSHOT + 0.1.12 diff --git a/pom.xml b/pom.xml index e864e9b..7c3d9c0 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.12-SNAPSHOT + 0.1.12 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 36029e6..e892416 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.12-SNAPSHOT + 0.1.12 Cap'n Proto runtime library org.capnproto From 059252cba5b70e09831dc7152decc218b83b7b91 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Tue, 5 Oct 2021 17:17:15 -0400 Subject: [PATCH 31/37] bump to v0.1.13-SNAPSHOT --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index c5712f6..d3108d6 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.12 + 0.1.13-SNAPSHOT capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.12 + 0.1.13-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index 2f5052b..e0e1ed7 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.12 + 0.1.13-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.12 + 0.1.13-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index 310db14..620bf5b 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.12 + 0.1.13-SNAPSHOT capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.12 + 0.1.13-SNAPSHOT diff --git a/pom.xml b/pom.xml index 7c3d9c0..7246f19 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.12 + 0.1.13-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index e892416..23c5627 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.12 + 0.1.13-SNAPSHOT Cap'n Proto runtime library org.capnproto From ab303cbc280c39827ec61311a812b508b11070c8 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Fri, 8 Oct 2021 14:24:22 -0400 Subject: [PATCH 32/37] add more robustness to integer wrapping problems --- .../java/org/capnproto/test/EncodingTest.java | 36 +++++++++++++++++++ .../java/org/capnproto/StructPointer.java | 10 +++--- .../main/java/org/capnproto/WireHelpers.java | 31 ++++++++-------- .../java/org/capnproto/StructPointerTest.java | 27 ++++++++++++++ 4 files changed, 84 insertions(+), 20 deletions(-) diff --git a/compiler/src/test/java/org/capnproto/test/EncodingTest.java b/compiler/src/test/java/org/capnproto/test/EncodingTest.java index f52afd4..6221fa7 100644 --- a/compiler/src/test/java/org/capnproto/test/EncodingTest.java +++ b/compiler/src/test/java/org/capnproto/test/EncodingTest.java @@ -875,4 +875,40 @@ public class EncodingTest { TestUtil.checkTestMessage(root2.getAs(Test.TestAllTypes.factory)); } + + @org.junit.Test + public void testZeroPointerUnderflow() throws DecodeException { + byte[] bytes = new byte[8 + 8 * 65535]; + bytes[4] = -1; + bytes[5] = -1; // struct pointer with 65535 words of data section. + for (int ii = 0; ii < 8 * 65535; ++ii) { + bytes[8 + ii] = 101; // populate the data section with sentinel data + } + ByteBuffer segment = ByteBuffer.wrap(bytes); + segment.order(ByteOrder.LITTLE_ENDIAN); + MessageReader message1 = new MessageReader(new ByteBuffer[]{segment}, + ReaderOptions.DEFAULT_READER_OPTIONS); + Test.TestAnyPointer.Reader message1RootReader = message1.getRoot(Test.TestAnyPointer.factory); + + MessageBuilder message2Builder = + new MessageBuilder(3 * 65535); // ample space to avoid far pointers + Test.TestAnyPointer.Builder message2RootBuilder = + message2Builder.getRoot(Test.TestAnyPointer.factory); + + // Copy the struct that has the sentinel data. + message2RootBuilder.getAnyPointerField().setAs(Test.TestAnyPointer.factory, message1RootReader); + + // Now clear the struct pointer. + message2RootBuilder.getAnyPointerField().clear(); + + java.nio.ByteBuffer[] outputSegments = message2Builder.getSegmentsForOutput(); + Assert.assertEquals(1, outputSegments.length); + Assert.assertEquals(0L, outputSegments[0].getLong(8)); // null because cleared + + Assert.assertEquals(16 + 8 * 65535, outputSegments[0].limit()); + for (int ii = 0; ii < 65535; ++ii) { + // All of the data should have been cleared. + Assert.assertEquals(0L, outputSegments[0].getLong((2 + ii) * 8)); + } + } } diff --git a/runtime/src/main/java/org/capnproto/StructPointer.java b/runtime/src/main/java/org/capnproto/StructPointer.java index 75d9930..855ea74 100644 --- a/runtime/src/main/java/org/capnproto/StructPointer.java +++ b/runtime/src/main/java/org/capnproto/StructPointer.java @@ -24,17 +24,17 @@ package org.capnproto; import java.nio.ByteBuffer; final class StructPointer{ - public static short dataSize(long ref) { + public static int dataSize(long ref) { // in words. - return (short)(WirePointer.upper32Bits(ref) & 0xffff); + return WirePointer.upper32Bits(ref) & 0xffff; } - public static short ptrCount(long ref) { - return (short)(WirePointer.upper32Bits(ref) >>> 16); + public static int ptrCount(long ref) { + return WirePointer.upper32Bits(ref) >>> 16; } public static int wordSize(long ref) { - return Short.toUnsignedInt(dataSize(ref)) + Short.toUnsignedInt(ptrCount(ref)); + return dataSize(ref) + ptrCount(ref); } public static void setFromStructSize(ByteBuffer buffer, int offset, StructSize size) { diff --git a/runtime/src/main/java/org/capnproto/WireHelpers.java b/runtime/src/main/java/org/capnproto/WireHelpers.java index 4a57a89..f741d52 100644 --- a/runtime/src/main/java/org/capnproto/WireHelpers.java +++ b/runtime/src/main/java/org/capnproto/WireHelpers.java @@ -424,8 +424,8 @@ final class WireHelpers { } FollowBuilderFarsResult resolved = followBuilderFars(ref, target, segment); - short oldDataSize = StructPointer.dataSize(resolved.ref); - short oldPointerCount = StructPointer.ptrCount(resolved.ref); + int oldDataSize = StructPointer.dataSize(resolved.ref); + int oldPointerCount = StructPointer.ptrCount(resolved.ref); int oldPointerSection = resolved.ptr + oldDataSize; if (oldDataSize < size.data || oldPointerCount < size.pointers) { @@ -472,7 +472,7 @@ final class WireHelpers { } else { return factory.constructBuilder(resolved.segment, resolved.ptr * Constants.BYTES_PER_WORD, oldPointerSection, oldDataSize * Constants.BITS_PER_WORD, - oldPointerCount); + (short)oldPointerCount); } } @@ -609,7 +609,7 @@ final class WireHelpers { throw new DecodeException("INLINE_COMPOSITE list with non-STRUCT elements not supported."); } int oldDataSize = StructPointer.dataSize(oldTag); - short oldPointerCount = StructPointer.ptrCount(oldTag); + int oldPointerCount = StructPointer.ptrCount(oldTag); int oldStep = (oldDataSize + oldPointerCount * Constants.POINTER_SIZE_IN_WORDS); int elementCount = WirePointer.inlineCompositeListElementCount(oldTag); @@ -618,7 +618,8 @@ final class WireHelpers { return factory.constructBuilder(resolved.segment, oldPtr * Constants.BYTES_PER_WORD, elementCount, oldStep * Constants.BITS_PER_WORD, - oldDataSize * Constants.BITS_PER_WORD, oldPointerCount); + oldDataSize * Constants.BITS_PER_WORD, + (short)oldPointerCount); } //# The structs in this list are smaller than expected, probably written using an older @@ -926,21 +927,21 @@ final class WireHelpers { resolved.segment.arena.checkReadLimit(StructPointer.wordSize(resolved.ref)); return factory.constructReader(resolved.segment, - resolved.ptr * Constants.BYTES_PER_WORD, - (resolved.ptr + dataSizeWords), - dataSizeWords * Constants.BITS_PER_WORD, - StructPointer.ptrCount(resolved.ref), - nestingLimit - 1); + resolved.ptr * Constants.BYTES_PER_WORD, + (resolved.ptr + dataSizeWords), + dataSizeWords * Constants.BITS_PER_WORD, + (short)StructPointer.ptrCount(resolved.ref), + nestingLimit - 1); } static SegmentBuilder setStructPointer(SegmentBuilder segment, int refOffset, StructReader value) { - short dataSize = (short)roundBitsUpToWords(value.dataSize); + int dataSize = roundBitsUpToWords(value.dataSize); int totalSize = dataSize + value.pointerCount * Constants.POINTER_SIZE_IN_WORDS; AllocateResult allocation = allocate(refOffset, segment, totalSize, WirePointer.STRUCT); StructPointer.set(allocation.segment.buffer, allocation.refOffset, - dataSize, value.pointerCount); + (short)dataSize, value.pointerCount); if (value.dataSize == 1) { throw new RuntimeException("single bit case not handled"); @@ -1066,7 +1067,7 @@ final class WireHelpers { resolved.ptr * Constants.BYTES_PER_WORD, resolved.ptr + StructPointer.dataSize(resolved.ref), StructPointer.dataSize(resolved.ref) * Constants.BITS_PER_WORD, - StructPointer.ptrCount(resolved.ref), + (short)StructPointer.ptrCount(resolved.ref), nestingLimit - 1)); case WirePointer.LIST : byte elementSize = ListPointer.elementSize(resolved.ref); @@ -1102,7 +1103,7 @@ final class WireHelpers { elementCount, wordsPerElement * Constants.BITS_PER_WORD, StructPointer.dataSize(tag) * Constants.BITS_PER_WORD, - StructPointer.ptrCount(tag), + (short)StructPointer.ptrCount(tag), nestingLimit - 1)); } else { int dataSize = ElementSize.dataBitsPerElement(elementSize); @@ -1203,7 +1204,7 @@ final class WireHelpers { size, wordsPerElement * Constants.BITS_PER_WORD, StructPointer.dataSize(tag) * Constants.BITS_PER_WORD, - StructPointer.ptrCount(tag), + (short)StructPointer.ptrCount(tag), nestingLimit - 1); } default : { diff --git a/runtime/src/test/java/org/capnproto/StructPointerTest.java b/runtime/src/test/java/org/capnproto/StructPointerTest.java index d1a3af3..f39ae0e 100644 --- a/runtime/src/test/java/org/capnproto/StructPointerTest.java +++ b/runtime/src/test/java/org/capnproto/StructPointerTest.java @@ -4,6 +4,33 @@ import org.junit.Assert; import org.junit.Test; public class StructPointerTest { + @Test + public void testDataSize() { + Assert.assertEquals( + 2, + StructPointer.dataSize(0x0001000200000000L)); + } + + @Test + public void testDataSizeUnderflow() { + Assert.assertEquals( + 0xffff, + StructPointer.dataSize(0x0001ffff00000000L)); + } + + @Test + public void testPtrCount() { + Assert.assertEquals( + 1, + StructPointer.ptrCount(0x0001000200000000L)); + } + + @Test + public void testPtrCountUnderflow() { + Assert.assertEquals( + 0xffff, + StructPointer.ptrCount(0xffff000200000000L)); + } @Test public void testWordSize() { From 3474af397336d2fce1efaa9b67690c7515b0f5c7 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 11 Oct 2021 10:57:32 -0400 Subject: [PATCH 33/37] prepare for v0.1.13 release --- CHANGELOG.md | 3 +++ benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f61308..33d933b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## v0.1.13 +- Improved robustness to StructPointer integer wrapping problems. + ## v0.1.12 - Fix bug in StructPointer.wordSize() found by Martin Dindoffer. diff --git a/benchmark/pom.xml b/benchmark/pom.xml index d3108d6..b5a96d3 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.13-SNAPSHOT + 0.1.13 capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.13-SNAPSHOT + 0.1.13 diff --git a/compiler/pom.xml b/compiler/pom.xml index e0e1ed7..112d5c6 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.13-SNAPSHOT + 0.1.13 capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.13-SNAPSHOT + 0.1.13 diff --git a/examples/pom.xml b/examples/pom.xml index 620bf5b..98dfc33 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.13-SNAPSHOT + 0.1.13 capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.13-SNAPSHOT + 0.1.13 diff --git a/pom.xml b/pom.xml index 7246f19..f58782f 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.13-SNAPSHOT + 0.1.13 Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 23c5627..34de0a3 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.13-SNAPSHOT + 0.1.13 Cap'n Proto runtime library org.capnproto From 0eb4abed7a2ff039011a8fb7a1c548600f0bfc39 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 11 Oct 2021 11:06:05 -0400 Subject: [PATCH 34/37] bump to 0.1.14-SNAPSHOT --- benchmark/pom.xml | 4 ++-- compiler/pom.xml | 4 ++-- examples/pom.xml | 4 ++-- pom.xml | 2 +- runtime/pom.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/benchmark/pom.xml b/benchmark/pom.xml index b5a96d3..c366960 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -5,7 +5,7 @@ benchmark jar capnproto-java benchmark - 0.1.13 + 0.1.14-SNAPSHOT capnproto-java benchmark org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.13 + 0.1.14-SNAPSHOT diff --git a/compiler/pom.xml b/compiler/pom.xml index 112d5c6..3e2b062 100644 --- a/compiler/pom.xml +++ b/compiler/pom.xml @@ -5,7 +5,7 @@ compiler jar schema compiler plugin for java - 0.1.13 + 0.1.14-SNAPSHOT capnpc-java org.capnproto @@ -45,7 +45,7 @@ org.capnproto runtime - 0.1.13 + 0.1.14-SNAPSHOT diff --git a/examples/pom.xml b/examples/pom.xml index 98dfc33..d35ed98 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ examples jar capnproto-java examples - 0.1.13 + 0.1.14-SNAPSHOT capnproto-java examples org.capnproto @@ -39,7 +39,7 @@ org.capnproto runtime - 0.1.13 + 0.1.14-SNAPSHOT diff --git a/pom.xml b/pom.xml index f58782f..0a5880e 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.capnproto capnproto-java pom - 0.1.13 + 0.1.14-SNAPSHOT Cap'n Proto for Java https://capnproto.org/ diff --git a/runtime/pom.xml b/runtime/pom.xml index 34de0a3..e395a55 100644 --- a/runtime/pom.xml +++ b/runtime/pom.xml @@ -5,7 +5,7 @@ runtime jar runtime - 0.1.13 + 0.1.14-SNAPSHOT Cap'n Proto runtime library org.capnproto From 2f7ce185bb72f98f804bf1e75f6d9f72655da4ed Mon Sep 17 00:00:00 2001 From: Martin Dindoffer Date: Mon, 11 Oct 2021 15:12:00 +0200 Subject: [PATCH 35/37] Add advisories for recently found vulnearbilities --- .../2021-09-30-0-cpu-amplification.md | 57 +++++++++++++++++++ ...021-09-30-1-excessive-memory-allocation.md | 54 ++++++++++++++++++ .../2021-10-04-0-cpu-amplification.md | 47 +++++++++++++++ 3 files changed, 158 insertions(+) create mode 100644 security-advisories/2021-09-30-0-cpu-amplification.md create mode 100644 security-advisories/2021-09-30-1-excessive-memory-allocation.md create mode 100644 security-advisories/2021-10-04-0-cpu-amplification.md diff --git a/security-advisories/2021-09-30-0-cpu-amplification.md b/security-advisories/2021-09-30-0-cpu-amplification.md new file mode 100644 index 0000000..d0be8a6 --- /dev/null +++ b/security-advisories/2021-09-30-0-cpu-amplification.md @@ -0,0 +1,57 @@ +Problem +======= + +CPU usage amplification attack + +Discovered by +============= + +Martin Dindoffer <contact@dindoffer.eu> + +Announced +========= + +2021-09-30 + +Impact +====== + +It is possible for an attacker to craft a small malicious message that will contain large lists with no data, leading to +artificial load on the system and possibly a Denial of Service attack. + +CVSS score +========== + +5.9 (Medium) CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H + +Fixed in +======== + +Release 0.1.11 + +Details +======= + +Cap'n'Proto List pointer encodes the size of the list in the header as a 29 bit value. This value is read as a counter +for the list Iterator. Setting a large value for the elementCount may produce empty loops in the code that don't operate +on any data but still consume CPU time. + +List Amplification is a well known posibility in the Cap'n'Proto protocol, as can be seen in the Encoding +spec (https://capnproto.org/encoding.html): +> A list of Void values or zero-size structs can have a very large element count while taking constant space on the wire. +> If the receiving application expects a list of structs, it will see these zero-sized elements as valid structs set to their default values. +> If it iterates through the list processing each element, it could spend a large amount of CPU time or other resources despite the message being small. +> To defend against this, the “traversal limit” should count a list of zero-sized elements as if each element were one word instead. +> This rule was introduced in the C++ implementation in commit 1048706. + +A form of this traversal limit countermeasure is present in capnproto-java. However, the message may contain a huge list +with 1-bit elements that are read as a struct list. This combined with the fact that the data may simply be stripped +from the message makes it is possible to create problematically huge Iterators with default traversal limits. + +Remediation +=========== + +The iteration should take into account the actual message length. As a rule of thumb the parser should not enter loops +with an attacker-controlled iteration count that is not bounded by the input length. + +Therefore additional bounds checking was introduced to detect out-of-bounds list pointers. \ No newline at end of file diff --git a/security-advisories/2021-09-30-1-excessive-memory-allocation.md b/security-advisories/2021-09-30-1-excessive-memory-allocation.md new file mode 100644 index 0000000..2f54aca --- /dev/null +++ b/security-advisories/2021-09-30-1-excessive-memory-allocation.md @@ -0,0 +1,54 @@ +Problem +======= + +Insufficient validation of message metadata with negative segment sizes may lead to excessive memory allocation and +subsequent DoS. + +Discovered by +============= + +Martin Dindoffer <contact@dindoffer.eu> + +Announced +========= + +2021-09-30 + +Impact +====== + +It is possible for an attacker to craft a malicious message that may thanks to memory amplification lead to a Denial of +Service attack against the consumer of CapnProto messages. In practical terms a message of only 8 bytes may cause +allocation of 2GB of memory. + +CVSS score +========== + +7.5 (High) CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H + +Fixed in +======== + +Release 0.1.11 + +Details +======= + +A read of 4 bytes from the message is performed, the result of which is read as the size of a segment in a variable. +This size is stored in memory as a signed integer. If the segment count is 1, the size of the first segment is also +considered to be the total size of the message stored in a totalWords variable. Since both the segment0Size and the +totalWords are signed integers, they may hold a negative number which will pass the traversal limit check. + +Subsequently capnproto-java tries to allocate enough memory for the segment. Because the encoded size is in words, the +value is multiplied by the number 8. The resulting number is used as the size of a ByteBuffer allocated for the first +segment. A sufficiently large negative number when multiplied by 8 will net a large positive integer, thus causing large +memory allocation in the form of a ByteBuffer. + +A segment size of `-1 879 048 193` multiplied by 8 results in `2 147 483 640` bytes of allocated memory, which is close +to `Integer.MAX_VALUE` and around the size of the maximum length of a Java array. Therefore the maximum size a message +may allocate this way is roughly 2GB. + +Remediation +=========== + +Stricter validation refusing negative segment sizes was implemented. \ No newline at end of file diff --git a/security-advisories/2021-10-04-0-cpu-amplification.md b/security-advisories/2021-10-04-0-cpu-amplification.md new file mode 100644 index 0000000..cd23609 --- /dev/null +++ b/security-advisories/2021-10-04-0-cpu-amplification.md @@ -0,0 +1,47 @@ +Problem +======= + +Incorrect parsing of large list element sizes may lead to CPU usage amplification attack + +Discovered by +============= + +Martin Dindoffer <contact@dindoffer.eu> + +Announced +========= + +2021-10-04 + +Impact +====== + +It is possible for an attacker to craft a small malicious message that will contain large lists with no data, leading to +artificial load on the system and possibly a Denial of Service attack. + +CVSS score +========== + +5.9 (Medium) CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H + +Fixed in +======== + +Release 0.1.12 + +Details +======= + +A tag pointer encodes the size of the elements in words and the total number of elements. Validation of these values is +performed in the code, but only as an overflow check of their product (against the total wordcount encoded in the list +pointer). The element size is read as a `short` value with improper casting to signed integers. Therefore, it is +possible to craft a message that will encode a large amount of elements (up to `2^30`) and offset this bloated size by +specifying a negative size of the elements (in words). There is no need to encode the actual payload for the large list, +thus capnproto-java will generate Iterators with large iteration counts over empty payload with messages of well under +100 bytes, that may put CPU under loads heavy enough to easily perform DoS attacks. + +Remediation +=========== + +The `short` values of the list element sizes are now parsed as unsigned values, making sure that the list overflow check +will catch the huge list size. \ No newline at end of file From 84dcb1008585e2460f9220f3a750450837e0cf0a Mon Sep 17 00:00:00 2001 From: Vaci Koblizek Date: Wed, 10 Nov 2021 11:40:10 +0000 Subject: [PATCH 36/37] correct pom version --- runtime-rpc/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime-rpc/pom.xml b/runtime-rpc/pom.xml index 1d84354..aed0815 100644 --- a/runtime-rpc/pom.xml +++ b/runtime-rpc/pom.xml @@ -5,7 +5,7 @@ runtime-rpc jar runtime-rpc - 0.1.10-SNAPSHOT + 0.1.14-SNAPSHOT Cap'n Proto RPC runtime library org.capnproto @@ -49,12 +49,12 @@ org.capnproto runtime - 0.1.10-SNAPSHOT + 0.1.14-SNAPSHOT org.capnproto compiler - 0.1.10-SNAPSHOT + 0.1.14-SNAPSHOT From 9bb1032274bda10891f1f2bf8caf901cc171ff8d Mon Sep 17 00:00:00 2001 From: Vaci Koblizek Date: Wed, 10 Nov 2021 12:13:13 +0000 Subject: [PATCH 37/37] avoid truncating struct size --- runtime/src/main/java/org/capnproto/WireHelpers.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/main/java/org/capnproto/WireHelpers.java b/runtime/src/main/java/org/capnproto/WireHelpers.java index 275f9b4..bc87d6b 100644 --- a/runtime/src/main/java/org/capnproto/WireHelpers.java +++ b/runtime/src/main/java/org/capnproto/WireHelpers.java @@ -1008,7 +1008,7 @@ final class WireHelpers { } static SegmentBuilder setStructPointer(SegmentBuilder segment, CapTableBuilder capTable, int refOffset, StructReader value) { - short dataSize = (short)roundBitsUpToWords(value.dataSize); + int dataSize = roundBitsUpToWords(value.dataSize); int totalSize = dataSize + value.pointerCount * Constants.POINTER_SIZE_IN_WORDS; AllocateResult allocation = allocate(refOffset, segment, capTable, totalSize, WirePointer.STRUCT);