From 54dc4395b90d5a563bad45b381cba663d68370c6 Mon Sep 17 00:00:00 2001 From: Wouter van Oortmerssen Date: Mon, 30 Nov 2015 11:25:21 -0800 Subject: [PATCH] Java builder now checks if buffer was finished upon access. Also checks for nesting of objects in vector construction. This avoids common errors in FlatBuffer construction. Change-Id: I5507c5d767684e20e94883a92448f05acefba4d6 Tested: on Linux. --- java/com/google/flatbuffers/FlatBufferBuilder.java | 46 ++++++++++++++++------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/java/com/google/flatbuffers/FlatBufferBuilder.java b/java/com/google/flatbuffers/FlatBufferBuilder.java index 368be2f..a6234ca 100644 --- a/java/com/google/flatbuffers/FlatBufferBuilder.java +++ b/java/com/google/flatbuffers/FlatBufferBuilder.java @@ -28,18 +28,19 @@ import java.nio.charset.Charset; * main FlatBuffers documentation. */ public class FlatBufferBuilder { - ByteBuffer bb; // Where we construct the FlatBuffer. - int space; // Remaining space in the ByteBuffer. + ByteBuffer bb; // Where we construct the FlatBuffer. + int space; // Remaining space in the ByteBuffer. static final Charset utf8charset = Charset.forName("UTF-8"); - int minalign = 1; // Minimum alignment encountered so far. - int[] vtable = null; // The vtable for the current table. - int vtable_in_use = 0; // The amount of fields we're actually using. - boolean nested = false; // Whether we are currently serializing a table. - int object_start; // Starting offset of the current struct/table. - int[] vtables = new int[16]; // List of offsets of all vtables. - int num_vtables = 0; // Number of entries in `vtables` in use. - int vector_num_elems = 0; // For the current vector being built. - boolean force_defaults = false; // False omits default values from the serialized data + int minalign = 1; // Minimum alignment encountered so far. + int[] vtable = null; // The vtable for the current table. + int vtable_in_use = 0; // The amount of fields we're actually using. + boolean nested = false; // Whether we are currently serializing a table. + boolean finished = false; // Whether the buffer is finished. + int object_start; // Starting offset of the current struct/table. + int[] vtables = new int[16]; // List of offsets of all vtables. + int num_vtables = 0; // Number of entries in `vtables` in use. + int vector_num_elems = 0; // For the current vector being built. + boolean force_defaults = false; // False omits default values from the serialized data /** * Start with a buffer of size {@code initial_size}, then grow as required. @@ -86,6 +87,7 @@ public class FlatBufferBuilder { space = bb.capacity(); vtable_in_use = 0; nested = false; + finished = false; object_start = 0; num_vtables = 0; vector_num_elems = 0; @@ -240,6 +242,7 @@ public class FlatBufferBuilder { vector_num_elems = num_elems; prep(SIZEOF_INT, elem_size * num_elems); prep(alignment, elem_size * num_elems); // Just in case alignment > int. + nested = true; } /** @@ -250,6 +253,9 @@ public class FlatBufferBuilder { * @see #startVector(int, int, int) */ public int endVector() { + if (!nested) + throw new AssertionError("FlatBuffers: endVector called without startVector"); + nested = false; putInt(vector_num_elems); return offset(); } @@ -285,6 +291,16 @@ public class FlatBufferBuilder { } /** + * Should not be accessing the final buffer before it is finished. + */ + public void finished() { + if (!finished) + throw new AssertionError( + "FlatBuffers: you can only access the serialized buffer after it has been" + + " finished by FlatBufferBuilder.finish()."); + } + + /** * Should not be creating any other object, string or vector * while an object is being constructed */ @@ -452,6 +468,7 @@ public class FlatBufferBuilder { prep(minalign, SIZEOF_INT); addOffset(root_table); bb.position(space); + finished = true; } public void finish(int root_table, String file_identifier) { @@ -481,7 +498,10 @@ public class FlatBufferBuilder { // Get the ByteBuffer representing the FlatBuffer. Only call this after you've // called finish(). The actual data starts at the ByteBuffer's current position, // not necessarily at 0. - public ByteBuffer dataBuffer() { return bb; } + public ByteBuffer dataBuffer() { + finished(); + return bb; + } /** * The FlatBuffer data doesn't start at offset 0 in the {@link ByteBuffer}, but @@ -493,6 +513,7 @@ public class FlatBufferBuilder { */ @Deprecated private int dataStart() { + finished(); return space; } @@ -506,6 +527,7 @@ public class FlatBufferBuilder { * @throws IndexOutOfBoundsException If the range of bytes is ouf of bound */ public byte[] sizedByteArray(int start, int length){ + finished(); byte[] array = new byte[length]; bb.position(start); bb.get(array); -- 2.7.4