Commit 68996fc8 authored by kenton@google.com's avatar kenton@google.com

Gigantic descriptors shouldn't overflow the Java string literal size limit.

parent 445f1023
......@@ -112,6 +112,7 @@
<arg value="../src/google/protobuf/unittest_lite.proto" />
<arg value="../src/google/protobuf/unittest_import_lite.proto" />
<arg value="../src/google/protobuf/unittest_lite_imports_nonlite.proto" />
<arg value="../src/google/protobuf/unittest_enormous_descriptor.proto" />
</exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
......
......@@ -244,7 +244,8 @@ public final class Descriptors {
* encoded in protocol buffer wire format.
*/
public static void internalBuildGeneratedFileFrom(
final String descriptorData, final FileDescriptor[] dependencies,
final String[] descriptorDataParts,
final FileDescriptor[] dependencies,
final InternalDescriptorAssigner descriptorAssigner) {
// Hack: We can't embed a raw byte array inside generated Java code
// (at least, not efficiently), but we can embed Strings. So, the
......@@ -255,9 +256,16 @@ public final class Descriptors {
// serialized form. So, if we convert it to bytes in ISO-8859-1, we
// should get the original bytes that we want.
// descriptorData may contain multiple strings in order to get around the
// Java 64k string literal limit.
StringBuilder descriptorData = new StringBuilder();
for (String part : descriptorDataParts) {
descriptorData.append(part);
}
final byte[] descriptorBytes;
try {
descriptorBytes = descriptorData.getBytes("ISO-8859-1");
descriptorBytes = descriptorData.toString().getBytes("ISO-8859-1");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(
"Standard encoding ISO-8859-1 not supported by JVM.", e);
......
......@@ -397,4 +397,12 @@ public class DescriptorsTest extends TestCase {
assertEquals(values1[i].toString(), values2[i].toString());
}
}
public void testEnormousDescriptor() throws Exception {
// The descriptor for this file is larger than 64k, yet it did not cause
// a compiler error due to an over-long string literal.
assertTrue(
UnittestEnormousDescriptor.getDescriptor()
.toProto().getSerializedSize() > 65536);
}
}
......@@ -186,6 +186,7 @@ protoc_inputs = \
google/protobuf/unittest_lite.proto \
google/protobuf/unittest_import_lite.proto \
google/protobuf/unittest_lite_imports_nonlite.proto \
google/protobuf/unittest_enormous_descriptor.proto \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
EXTRA_DIST = \
......@@ -225,6 +226,8 @@ protoc_outputs = \
google/protobuf/unittest_custom_options.pb.h \
google/protobuf/unittest_lite_imports_nonlite.pb.cc \
google/protobuf/unittest_lite_imports_nonlite.pb.h \
google/protobuf/unittest_enormous_descriptor.pb.cc \
google/protobuf/unittest_enormous_descriptor.pb.h \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \
google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h
......
......@@ -256,20 +256,28 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) {
"private static com.google.protobuf.Descriptors.FileDescriptor\n"
" descriptor;\n"
"static {\n"
" java.lang.String descriptorData =\n");
" java.lang.String[] descriptorData = {\n");
printer->Indent();
printer->Indent();
// Only write 40 bytes per line.
static const int kBytesPerLine = 40;
for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
if (i > 0) printer->Print(" +\n");
if (i > 0) {
// Every 400 lines, start a new string literal, in order to avoid the
// 64k length limit.
if (i % 400 == 0) {
printer->Print(",\n");
} else {
printer->Print(" +\n");
}
}
printer->Print("\"$data$\"",
"data", CEscape(file_data.substr(i, kBytesPerLine)));
}
printer->Print(";\n");
printer->Outdent();
printer->Print("\n};\n");
// -----------------------------------------------------------------
// Create the InternalDescriptorAssigner.
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment