diff options
Diffstat (limited to 'java')
4 files changed, 94 insertions, 4 deletions
diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java index c4fdfe64..2d949b65 100644 --- a/java/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/src/main/java/com/google/protobuf/TextFormat.java @@ -384,12 +384,24 @@ public final class TextFormat { private int previousLine = 0; private int previousColumn = 0; - private static Pattern WHITESPACE = Pattern.compile("(\\s|(#[^\n]*$))*"); + private static Pattern WHITESPACE = + Pattern.compile("(\\s|(#.*$))+", Pattern.MULTILINE); private static Pattern TOKEN = Pattern.compile( "[a-zA-Z_][0-9a-zA-Z_+-]*|" + // an identifier "[0-9+-][0-9a-zA-Z_.+-]*|" + // a number - "\"([^\"\n\\\\]|\\\\[^\n])*(\"|\\\\?$)|" + // a double-quoted string - "\'([^\"\n\\\\]|\\\\[^\n])*(\'|\\\\?$)"); // a single-quoted string + "\"([^\"\n\\\\]|\\\\.)*(\"|\\\\?$)|" + // a double-quoted string + "\'([^\"\n\\\\]|\\\\.)*(\'|\\\\?$)", // a single-quoted string + Pattern.MULTILINE); + + private static Pattern DOUBLE_INFINITY = Pattern.compile( + "-?inf(inity)?", + Pattern.CASE_INSENSITIVE); + private static Pattern FLOAT_INFINITY = Pattern.compile( + "-?inf(inity)?f?", + Pattern.CASE_INSENSITIVE); + private static Pattern FLOAT_NAN = Pattern.compile( + "nanf?", + Pattern.CASE_INSENSITIVE); /** Construct a tokenizer that parses tokens from the given text. */ public Tokenizer(CharSequence text) { @@ -570,6 +582,17 @@ public final class TextFormat { * Otherwise, throw a {@link ParseException}. */ public double consumeDouble() throws ParseException { + // We need to parse infinity and nan separately because + // Double.parseDouble() does not accept "inf", "infinity", or "nan". + if (DOUBLE_INFINITY.matcher(currentToken).matches()) { + boolean negative = currentToken.startsWith("-"); + nextToken(); + return negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; + } + if (currentToken.equalsIgnoreCase("nan")) { + nextToken(); + return Double.NaN; + } try { double result = Double.parseDouble(currentToken); nextToken(); @@ -584,6 +607,17 @@ public final class TextFormat { * Otherwise, throw a {@link ParseException}. */ public float consumeFloat() throws ParseException { + // We need to parse infinity and nan separately because + // Float.parseFloat() does not accept "inf", "infinity", or "nan". + if (FLOAT_INFINITY.matcher(currentToken).matches()) { + boolean negative = currentToken.startsWith("-"); + nextToken(); + return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; + } + if (FLOAT_NAN.matcher(currentToken).matches()) { + nextToken(); + return Float.NaN; + } try { float result = Float.parseFloat(currentToken); nextToken(); diff --git a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java index 6bcc4309..ba4dd5ad 100644 --- a/java/src/main/java/com/google/protobuf/UnknownFieldSet.java +++ b/java/src/main/java/com/google/protobuf/UnknownFieldSet.java @@ -387,7 +387,7 @@ public final class UnknownFieldSet { int number = WireFormat.getTagFieldNumber(tag); switch (WireFormat.getTagWireType(tag)) { case WireFormat.WIRETYPE_VARINT: - getFieldBuilder(number).addVarint(input.readInt32()); + getFieldBuilder(number).addVarint(input.readInt64()); return true; case WireFormat.WIRETYPE_FIXED64: getFieldBuilder(number).addFixed64(input.readFixed64()); diff --git a/java/src/test/java/com/google/protobuf/TextFormatTest.java b/java/src/test/java/com/google/protobuf/TextFormatTest.java index 2c485c55..8b7af107 100644 --- a/java/src/test/java/com/google/protobuf/TextFormatTest.java +++ b/java/src/test/java/com/google/protobuf/TextFormatTest.java @@ -250,6 +250,36 @@ public class TextFormatTest extends TestCase { TestUtil.assertAllExtensionsSet(builder.build()); } + public void testParseCompatibility() throws Exception { + String original = "repeated_float: inf\n" + + "repeated_float: -inf\n" + + "repeated_float: nan\n" + + "repeated_float: inff\n" + + "repeated_float: -inff\n" + + "repeated_float: nanf\n" + + "repeated_float: 1.0f\n" + + "repeated_float: infinityf\n" + + "repeated_float: -Infinityf\n" + + "repeated_double: infinity\n" + + "repeated_double: -infinity\n" + + "repeated_double: nan\n"; + String canonical = "repeated_float: Infinity\n" + + "repeated_float: -Infinity\n" + + "repeated_float: NaN\n" + + "repeated_float: Infinity\n" + + "repeated_float: -Infinity\n" + + "repeated_float: NaN\n" + + "repeated_float: 1.0\n" + + "repeated_float: Infinity\n" + + "repeated_float: -Infinity\n" + + "repeated_double: Infinity\n" + + "repeated_double: -Infinity\n" + + "repeated_double: NaN\n"; + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TextFormat.merge(original, builder); + assertEquals(canonical, builder.build().toString()); + } + public void testParseExotic() throws Exception { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); TextFormat.merge(exoticText, builder); @@ -291,6 +321,17 @@ public class TextFormatTest extends TestCase { assertEquals(1, builder.getOptionalGroup().getA()); } + public void testParseComment() throws Exception { + TestAllTypes.Builder builder = TestAllTypes.newBuilder(); + TextFormat.merge( + "# this is a comment\n" + + "optional_int32: 1 # another comment\n" + + "optional_int64: 2\n" + + "# EOF comment", builder); + assertEquals(1, builder.getOptionalInt32()); + assertEquals(2, builder.getOptionalInt64()); + } + private void assertParseError(String error, String text) { TestAllTypes.Builder builder = TestAllTypes.newBuilder(); try { diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java index 0ad2683d..8919414e 100644 --- a/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java +++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java @@ -312,4 +312,19 @@ public class UnknownFieldSetTest extends TestCase { .getVarintList()); } } + + public void testLargeVarint() throws Exception { + ByteString data = + UnknownFieldSet.newBuilder() + .addField(1, + UnknownFieldSet.Field.newBuilder() + .addVarint(0x7FFFFFFFFFFFFFFFL) + .build()) + .build() + .toByteString(); + UnknownFieldSet parsed = UnknownFieldSet.parseFrom(data); + UnknownFieldSet.Field field = parsed.getField(1); + assertEquals(1, field.getVarintList().size()); + assertEquals(0x7FFFFFFFFFFFFFFFL, (long)field.getVarintList().get(0)); + } } |