diff --git a/Makefile b/Makefile index 493539b..af4c909 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ clean : rm -f capnpc-java capnpc-java.exe capnpc-java : $(CAPNPC_JAVA_SOURCES) - $(CXX) $(CAPNPC_JAVA_SOURCES) $(CXX_FLAGS) -o capnpc-java + $(CXX) $(CAPNPC_JAVA_SOURCES) $(CXX_FLAGS) $(CFLAGS) $(LDFLAGS) -o capnpc-java install: mkdir -p ${PREFIX}/bin diff --git a/runtime/src/main/java/org/capnproto/SegmentReader.java b/runtime/src/main/java/org/capnproto/SegmentReader.java index b407d21..62a30ef 100644 --- a/runtime/src/main/java/org/capnproto/SegmentReader.java +++ b/runtime/src/main/java/org/capnproto/SegmentReader.java @@ -44,6 +44,6 @@ public class SegmentReader { 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(); + 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 bc87d6b..6e09668 100644 --- a/runtime/src/main/java/org/capnproto/WireHelpers.java +++ b/runtime/src/main/java/org/capnproto/WireHelpers.java @@ -947,13 +947,18 @@ final class WireHelpers { int refTarget = WirePointer.target(refOffset, ref); FollowFarsResult resolved = followFars(ref, refTarget, segment); - int dataSizeWords = StructPointer.dataSize(resolved.ref); - if (WirePointer.kind(resolved.ref) != WirePointer.STRUCT) { throw new DecodeException("Message contains non-struct pointer where struct pointer was expected."); } - resolved.segment.arena.checkReadLimit(StructPointer.wordSize(resolved.ref)); + int dataSizeWords = StructPointer.dataSize(resolved.ref); + int ptrCount = StructPointer.ptrCount(resolved.ref); + int wordSize = dataSizeWords + ptrCount; + + resolved.segment.arena.checkReadLimit(wordSize); + if (!bounds_check(resolved.segment, resolved.ptr, wordSize)) { + throw new DecodeException("Message contains out-of-bounds struct pointer"); + } return factory.constructReader(resolved.segment, capTable, @@ -962,7 +967,6 @@ final class WireHelpers { dataSizeWords * Constants.BITS_PER_WORD, (short)StructPointer.ptrCount(resolved.ref), nestingLimit - 1); - } static StructReader readStructPointer(SegmentReader segment, diff --git a/runtime/src/test/java/org/capnproto/LayoutTest.java b/runtime/src/test/java/org/capnproto/LayoutTest.java index d023abb..b885fcd 100644 --- a/runtime/src/test/java/org/capnproto/LayoutTest.java +++ b/runtime/src/test/java/org/capnproto/LayoutTest.java @@ -63,6 +63,29 @@ public class LayoutTest { Assert.assertEquals(reader._getBooleanField(64), false); } + /** + * @see #122 + */ + @Test(expected = DecodeException.class) + public void readStructPointerShouldThrowDecodeExceptionOnOutOfBoundsStructPointer() { + byte[] brokenMSG = new byte[]{ + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, //declare word size of 7, with payload of only 6 words + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + ByteBuffer buffer = ByteBuffer.wrap(brokenMSG); + buffer.order(ByteOrder.LITTLE_ENDIAN); + + ReaderArena arena = new ReaderArena(new ByteBuffer[]{ buffer }, 0x7fffffffffffffffL); + + StructReader reader = WireHelpers.readStructPointer(new BareStructReader(), arena.tryGetSegment(0), null, 0, null, 0, 0x7fffffff); + } + private class BareStructBuilder implements StructBuilder.Factory { private StructSize structSize;