forked from BigfootDev/flatbuffers
Fixed a bugs in the Java runtime that could cause an index out of bounds exception.
Tested: on Windows. Change-Id: I0d4cdafc21690eb9a509ba31f21e80dacfb602ff
This commit is contained in:
@@ -28,7 +28,7 @@ import java.nio.charset.Charset;
|
||||
public class FlatBufferBuilder {
|
||||
ByteBuffer bb; // Where we construct the FlatBuffer.
|
||||
int space; // Remaining space in the ByteBuffer.
|
||||
final Charset utf8charset = Charset.forName("UTF-8");
|
||||
static final Charset utf8charset = Charset.forName("UTF-8");
|
||||
int minalign = 1; // Minimum alignment encountered so far.
|
||||
int[] vtable; // The vtable for the current table, null otherwise.
|
||||
int object_start; // Starting offset of the current struct/table.
|
||||
@@ -42,6 +42,7 @@ public class FlatBufferBuilder {
|
||||
|
||||
// Start with a buffer of size `initial_size`, then grow as required.
|
||||
public FlatBufferBuilder(int initial_size) {
|
||||
if (initial_size <= 0) initial_size = 1;
|
||||
space = initial_size;
|
||||
bb = newByteBuffer(new byte[initial_size]);
|
||||
}
|
||||
@@ -57,7 +58,7 @@ public class FlatBufferBuilder {
|
||||
ByteBuffer growByteBuffer(ByteBuffer bb) {
|
||||
byte[] old_buf = bb.array();
|
||||
int old_buf_size = old_buf.length;
|
||||
if ((old_buf_size & 0xC0000000) != 0)
|
||||
if ((old_buf_size & 0xC0000000) != 0) // Ensure we don't grow beyond what fits in an int.
|
||||
throw new AssertionError("FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
|
||||
int new_buf_size = old_buf_size << 1;
|
||||
byte[] new_buf = new byte[new_buf_size];
|
||||
@@ -135,7 +136,7 @@ public class FlatBufferBuilder {
|
||||
|
||||
public int createString(String s) {
|
||||
byte[] utf8 = s.getBytes(utf8charset);
|
||||
bb.put(--space, (byte)0);
|
||||
addByte((byte)0);
|
||||
startVector(1, utf8.length);
|
||||
System.arraycopy(utf8, 0, bb.array(), space -= utf8.length, utf8.length);
|
||||
return endVector();
|
||||
@@ -192,12 +193,12 @@ public class FlatBufferBuilder {
|
||||
for (int i = vtable.length - 1; i >= 0 ; i--) {
|
||||
// Offset relative to the start of the table.
|
||||
short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
|
||||
putShort(off);
|
||||
addShort(off);
|
||||
}
|
||||
|
||||
final int standard_fields = 2; // The fields below:
|
||||
putShort((short)(vtableloc - object_start));
|
||||
putShort((short)((vtable.length + standard_fields) * SIZEOF_SHORT));
|
||||
addShort((short)(vtableloc - object_start));
|
||||
addShort((short)((vtable.length + standard_fields) * SIZEOF_SHORT));
|
||||
|
||||
// Search for an existing vtable that matches the current one.
|
||||
int existing_vtable = 0;
|
||||
@@ -245,6 +246,11 @@ public class FlatBufferBuilder {
|
||||
|
||||
// The FlatBuffer data doesn't start at offset 0 in the ByteBuffer:
|
||||
public int dataStart() {
|
||||
return bb.array().length - offset();
|
||||
return space;
|
||||
}
|
||||
|
||||
// Utility function for copying a byte array that starts at 0.
|
||||
public byte[] sizedByteArray() {
|
||||
return Arrays.copyOfRange(bb.array(), dataStart(), bb.array().length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,8 @@ static void GenStructArgs(const StructDef &struct_def, std::string *code_ptr,
|
||||
static void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
|
||||
const char *nameprefix) {
|
||||
std::string &code = *code_ptr;
|
||||
code += " builder.prep(" + NumToString(struct_def.minalign) + ", 0);\n";
|
||||
code += " builder.prep(" + NumToString(struct_def.minalign) + ", ";
|
||||
code += NumToString(struct_def.bytesize) + ");\n";
|
||||
for (auto it = struct_def.fields.vec.rbegin();
|
||||
it != struct_def.fields.vec.rend();
|
||||
++it) {
|
||||
@@ -347,7 +348,8 @@ static void GenStruct(StructDef &struct_def,
|
||||
// Save out the generated code for a single Java class while adding
|
||||
// declaration boilerplate.
|
||||
static bool SaveClass(const Parser &parser, const Definition &def,
|
||||
const std::string &classcode, const std::string &path) {
|
||||
const std::string &classcode, const std::string &path,
|
||||
bool needs_imports) {
|
||||
if (!classcode.length()) return true;
|
||||
|
||||
std::string name_space_java;
|
||||
@@ -365,8 +367,10 @@ static bool SaveClass(const Parser &parser, const Definition &def,
|
||||
|
||||
std::string code = "// automatically generated, do not modify\n\n";
|
||||
code += "package " + name_space_java + ";\n\n";
|
||||
code += "import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n";
|
||||
code += "import flatbuffers.*;\n\n";
|
||||
if (needs_imports) {
|
||||
code += "import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n";
|
||||
code += "import flatbuffers.*;\n\n";
|
||||
}
|
||||
code += classcode;
|
||||
auto filename = name_space_dir + PATH_SEPARATOR + def.name + ".java";
|
||||
return SaveFile(filename.c_str(), code, false);
|
||||
@@ -383,7 +387,7 @@ bool GenerateJava(const Parser &parser,
|
||||
it != parser.enums_.vec.end(); ++it) {
|
||||
std::string enumcode;
|
||||
GenEnum(**it, &enumcode);
|
||||
if (!SaveClass(parser, **it, enumcode, path))
|
||||
if (!SaveClass(parser, **it, enumcode, path, false))
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -391,7 +395,7 @@ bool GenerateJava(const Parser &parser,
|
||||
it != parser.structs_.vec.end(); ++it) {
|
||||
std::string declcode;
|
||||
GenStruct(**it, &declcode, parser.root_struct_def);
|
||||
if (!SaveClass(parser, **it, declcode, path))
|
||||
if (!SaveClass(parser, **it, declcode, path, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,5 +17,5 @@ rem Compile then run the Java test.
|
||||
|
||||
set batch_file_dir=%~d0%~p0
|
||||
|
||||
javac -classpath %batch_file_dir%\..\java;%batch_file_dir% JavaTest.java
|
||||
javac -g -classpath %batch_file_dir%\..\java;%batch_file_dir% JavaTest.java
|
||||
java -classpath %batch_file_dir%\..\java;%batch_file_dir% JavaTest
|
||||
|
||||
@@ -44,9 +44,12 @@ class JavaTest {
|
||||
TestBuffer(bb, 0);
|
||||
|
||||
// Second, let's create a FlatBuffer from scratch in Java, and test it also.
|
||||
// We set up the same values as monsterdata.json:
|
||||
// We use an initial size of 1 to exercise the reallocation algorithm,
|
||||
// normally a size larger than the typical FlatBuffer you generate would be
|
||||
// better for performance.
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
|
||||
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(1024);
|
||||
// We set up the same values as monsterdata.json:
|
||||
|
||||
int str = fbb.createString("MyMonster");
|
||||
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
package MyGame.Example;
|
||||
|
||||
import java.nio.*;
|
||||
import java.lang.*;
|
||||
import java.util.*;
|
||||
import flatbuffers.*;
|
||||
|
||||
public class Any {
|
||||
public static final byte NONE = 0;
|
||||
public static final byte Monster = 1;
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
package MyGame.Example;
|
||||
|
||||
import java.nio.*;
|
||||
import java.lang.*;
|
||||
import java.util.*;
|
||||
import flatbuffers.*;
|
||||
|
||||
public class Color {
|
||||
public static final byte Red = 0;
|
||||
public static final byte Green = 1;
|
||||
|
||||
@@ -13,7 +13,7 @@ public class Test extends Struct {
|
||||
public byte b() { return bb.get(bb_pos + 2); }
|
||||
|
||||
public static int createTest(FlatBufferBuilder builder, short a, byte b) {
|
||||
builder.prep(2, 0);
|
||||
builder.prep(2, 4);
|
||||
builder.pad(1);
|
||||
builder.putByte(b);
|
||||
builder.putShort(a);
|
||||
|
||||
@@ -18,9 +18,9 @@ public class Vec3 extends Struct {
|
||||
public Test test3(Test obj) { return obj.__init(bb_pos + 26, bb); }
|
||||
|
||||
public static int createVec3(FlatBufferBuilder builder, float x, float y, float z, double test1, byte test2, short Test_a, byte Test_b) {
|
||||
builder.prep(16, 0);
|
||||
builder.prep(16, 32);
|
||||
builder.pad(2);
|
||||
builder.prep(2, 0);
|
||||
builder.prep(2, 4);
|
||||
builder.pad(1);
|
||||
builder.putByte(Test_b);
|
||||
builder.putShort(Test_a);
|
||||
|
||||
Reference in New Issue
Block a user