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;