Java fixes for 21.x (#12036)

* Fix mutability bug in Java proto lite: sub-messages inside of oneofs were not
being set as immutable. This would allow code to get a builder for a
sub-message and modify the original (supposedly immutable) copy.

PiperOrigin-RevId: 511598810

* Add casts to make protobuf compatible with Java 1.8 runtime.
Fix for: https://github.com/protocolbuffers/protobuf/issues/11393

PiperOrigin-RevId: 511807920

* Update Makefile.am

---------

Co-authored-by: Protobuf Team Bot <protobuf-github-bot@google.com>
pull/12098/head
Jerry Berg 2 years ago committed by GitHub
parent cd7f3bd478
commit 8e6b5d5303
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      Makefile.am
  2. 1
      java/core/BUILD.bazel
  3. 2
      java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java
  4. 28
      java/core/src/main/java/com/google/protobuf/BinaryWriter.java
  5. 2
      java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java
  6. 28
      java/core/src/main/java/com/google/protobuf/CodedOutputStream.java
  7. 8
      java/core/src/main/java/com/google/protobuf/Internal.java
  8. 4
      java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java
  9. 67
      java/core/src/main/java/com/google/protobuf/Java8Compatibility.java
  10. 6
      java/core/src/main/java/com/google/protobuf/MessageSchema.java
  11. 11
      java/core/src/main/java/com/google/protobuf/NioByteString.java
  12. 2
      java/core/src/main/java/com/google/protobuf/TextFormat.java
  13. 10
      java/core/src/main/java/com/google/protobuf/Utf8.java
  14. 1
      java/lite/pom.xml
  15. 24
      java/lite/src/test/java/com/google/protobuf/LiteTest.java
  16. 1
      src/google/protobuf/unittest_lite.proto

@ -343,6 +343,7 @@ java_EXTRA_DIST=
java/core/src/main/java/com/google/protobuf/Internal.java \ java/core/src/main/java/com/google/protobuf/Internal.java \
java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \ java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java \
java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java \ java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java \
java/core/src/main/java/com/google/protobuf/Java8Compatibility.java \
java/core/src/main/java/com/google/protobuf/JavaType.java \ java/core/src/main/java/com/google/protobuf/JavaType.java \
java/core/src/main/java/com/google/protobuf/LazyField.java \ java/core/src/main/java/com/google/protobuf/LazyField.java \
java/core/src/main/java/com/google/protobuf/LazyFieldLite.java \ java/core/src/main/java/com/google/protobuf/LazyFieldLite.java \

@ -49,6 +49,7 @@ LITE_SRCS = [
"src/main/java/com/google/protobuf/Internal.java", "src/main/java/com/google/protobuf/Internal.java",
"src/main/java/com/google/protobuf/InvalidProtocolBufferException.java", "src/main/java/com/google/protobuf/InvalidProtocolBufferException.java",
"src/main/java/com/google/protobuf/IterableByteBufferInputStream.java", "src/main/java/com/google/protobuf/IterableByteBufferInputStream.java",
"src/main/java/com/google/protobuf/Java8Compatibility.java",
"src/main/java/com/google/protobuf/JavaType.java", "src/main/java/com/google/protobuf/JavaType.java",
"src/main/java/com/google/protobuf/LazyField.java", "src/main/java/com/google/protobuf/LazyField.java",
"src/main/java/com/google/protobuf/LazyFieldLite.java", "src/main/java/com/google/protobuf/LazyFieldLite.java",

@ -189,7 +189,7 @@ abstract class AllocatedBuffer {
@Override @Override
public AllocatedBuffer position(int position) { public AllocatedBuffer position(int position) {
buffer.position(position); Java8Compatibility.position(buffer, position);
return this; return this;
} }

@ -2019,8 +2019,8 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
buffers.addFirst(allocatedBuffer); buffers.addFirst(allocatedBuffer);
buffer = nioBuffer; buffer = nioBuffer;
buffer.limit(buffer.capacity()); Java8Compatibility.limit(buffer, buffer.capacity());
buffer.position(0); Java8Compatibility.position(buffer, 0);
// Set byte order to little endian for fast writing of fixed 32/64. // Set byte order to little endian for fast writing of fixed 32/64.
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
@ -2046,7 +2046,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
if (buffer != null) { if (buffer != null) {
totalDoneBytes += bytesWrittenToCurrentBuffer(); totalDoneBytes += bytesWrittenToCurrentBuffer();
// Update the indices on the netty buffer. // Update the indices on the netty buffer.
buffer.position(pos + 1); Java8Compatibility.position(buffer, pos + 1);
buffer = null; buffer = null;
pos = 0; pos = 0;
limitMinusOne = 0; limitMinusOne = 0;
@ -2475,7 +2475,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(pos + 1); Java8Compatibility.position(buffer, pos + 1);
buffer.put(value, offset, length); buffer.put(value, offset, length);
} }
@ -2494,7 +2494,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(pos + 1); Java8Compatibility.position(buffer, pos + 1);
buffer.put(value, offset, length); buffer.put(value, offset, length);
} }
@ -2506,7 +2506,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(pos + 1); Java8Compatibility.position(buffer, pos + 1);
buffer.put(value); buffer.put(value);
} }
@ -2526,7 +2526,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(pos + 1); Java8Compatibility.position(buffer, pos + 1);
buffer.put(value); buffer.put(value);
} }
@ -2576,8 +2576,8 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
buffers.addFirst(allocatedBuffer); buffers.addFirst(allocatedBuffer);
buffer = nioBuffer; buffer = nioBuffer;
buffer.limit(buffer.capacity()); Java8Compatibility.limit(buffer, buffer.capacity());
buffer.position(0); Java8Compatibility.position(buffer, 0);
bufferOffset = UnsafeUtil.addressOffset(buffer); bufferOffset = UnsafeUtil.addressOffset(buffer);
limitMinusOne = bufferOffset + (buffer.limit() - 1); limitMinusOne = bufferOffset + (buffer.limit() - 1);
@ -2602,7 +2602,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
if (buffer != null) { if (buffer != null) {
totalDoneBytes += bytesWrittenToCurrentBuffer(); totalDoneBytes += bytesWrittenToCurrentBuffer();
// Update the indices on the netty buffer. // Update the indices on the netty buffer.
buffer.position(bufferPos() + 1); Java8Compatibility.position(buffer, bufferPos() + 1);
buffer = null; buffer = null;
pos = 0; pos = 0;
limitMinusOne = 0; limitMinusOne = 0;
@ -3016,7 +3016,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(bufferPos() + 1); Java8Compatibility.position(buffer, bufferPos() + 1);
buffer.put(value, offset, length); buffer.put(value, offset, length);
} }
@ -3035,7 +3035,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(bufferPos() + 1); Java8Compatibility.position(buffer, bufferPos() + 1);
buffer.put(value, offset, length); buffer.put(value, offset, length);
} }
@ -3047,7 +3047,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(bufferPos() + 1); Java8Compatibility.position(buffer, bufferPos() + 1);
buffer.put(value); buffer.put(value);
} }
@ -3067,7 +3067,7 @@ abstract class BinaryWriter extends ByteOutput implements Writer {
} }
pos -= length; pos -= length;
buffer.position(bufferPos() + 1); Java8Compatibility.position(buffer, bufferPos() + 1);
buffer.put(value); buffer.put(value);
} }

@ -107,7 +107,7 @@ final class ByteBufferWriter {
} }
} finally { } finally {
// Restore the initial position. // Restore the initial position.
buffer.position(initialPos); Java8Compatibility.position(buffer, initialPos);
} }
} }

@ -1271,7 +1271,7 @@ public abstract class CodedOutputStream extends ByteOutput {
write(value.array(), value.arrayOffset(), value.capacity()); write(value.array(), value.arrayOffset(), value.capacity());
} else { } else {
ByteBuffer duplicated = value.duplicate(); ByteBuffer duplicated = value.duplicate();
duplicated.clear(); Java8Compatibility.clear(duplicated);
write(duplicated); write(duplicated);
} }
} }
@ -1522,7 +1522,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override @Override
public void flush() { public void flush() {
// Update the position on the buffer. // Update the position on the buffer.
byteBuffer.position(initialPosition + getTotalBytesWritten()); Java8Compatibility.position(byteBuffer, initialPosition + getTotalBytesWritten());
} }
} }
@ -1684,7 +1684,7 @@ public abstract class CodedOutputStream extends ByteOutput {
write(value.array(), value.arrayOffset(), value.capacity()); write(value.array(), value.arrayOffset(), value.capacity());
} else { } else {
ByteBuffer duplicated = value.duplicate(); ByteBuffer duplicated = value.duplicate();
duplicated.clear(); Java8Compatibility.clear(duplicated);
write(duplicated); write(duplicated);
} }
} }
@ -1794,18 +1794,18 @@ public abstract class CodedOutputStream extends ByteOutput {
// Save the current position and increment past the length field. We'll come back // Save the current position and increment past the length field. We'll come back
// and write the length field after the encoding is complete. // and write the length field after the encoding is complete.
final int startOfBytes = buffer.position() + minLengthVarIntSize; final int startOfBytes = buffer.position() + minLengthVarIntSize;
buffer.position(startOfBytes); Java8Compatibility.position(buffer, startOfBytes);
// Encode the string. // Encode the string.
encode(value); encode(value);
// Now go back to the beginning and write the length. // Now go back to the beginning and write the length.
int endOfBytes = buffer.position(); int endOfBytes = buffer.position();
buffer.position(startPos); Java8Compatibility.position(buffer, startPos);
writeUInt32NoTag(endOfBytes - startOfBytes); writeUInt32NoTag(endOfBytes - startOfBytes);
// Reposition the buffer past the written data. // Reposition the buffer past the written data.
buffer.position(endOfBytes); Java8Compatibility.position(buffer, endOfBytes);
} else { } else {
final int length = Utf8.encodedLength(value); final int length = Utf8.encodedLength(value);
writeUInt32NoTag(length); writeUInt32NoTag(length);
@ -1813,7 +1813,7 @@ public abstract class CodedOutputStream extends ByteOutput {
} }
} catch (UnpairedSurrogateException e) { } catch (UnpairedSurrogateException e) {
// Roll back the change and convert to an IOException. // Roll back the change and convert to an IOException.
buffer.position(startPos); Java8Compatibility.position(buffer, startPos);
// TODO(nathanmittler): We should throw an IOException here instead. // TODO(nathanmittler): We should throw an IOException here instead.
inefficientWriteStringNoTag(value, e); inefficientWriteStringNoTag(value, e);
@ -1826,7 +1826,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override @Override
public void flush() { public void flush() {
// Update the position of the original buffer. // Update the position of the original buffer.
originalBuffer.position(buffer.position()); Java8Compatibility.position(originalBuffer, buffer.position());
} }
@Override @Override
@ -2014,7 +2014,7 @@ public abstract class CodedOutputStream extends ByteOutput {
write(value.array(), value.arrayOffset(), value.capacity()); write(value.array(), value.arrayOffset(), value.capacity());
} else { } else {
ByteBuffer duplicated = value.duplicate(); ByteBuffer duplicated = value.duplicate();
duplicated.clear(); Java8Compatibility.clear(duplicated);
write(duplicated); write(duplicated);
} }
} }
@ -2150,7 +2150,7 @@ public abstract class CodedOutputStream extends ByteOutput {
// Save the current position and increment past the length field. We'll come back // Save the current position and increment past the length field. We'll come back
// and write the length field after the encoding is complete. // and write the length field after the encoding is complete.
int stringStart = bufferPos(position) + minLengthVarIntSize; int stringStart = bufferPos(position) + minLengthVarIntSize;
buffer.position(stringStart); Java8Compatibility.position(buffer, stringStart);
// Encode the string. // Encode the string.
Utf8.encodeUtf8(value, buffer); Utf8.encodeUtf8(value, buffer);
@ -2187,7 +2187,7 @@ public abstract class CodedOutputStream extends ByteOutput {
@Override @Override
public void flush() { public void flush() {
// Update the position of the original buffer. // Update the position of the original buffer.
originalBuffer.position(bufferPos(position)); Java8Compatibility.position(originalBuffer, bufferPos(position));
} }
@Override @Override
@ -2201,7 +2201,7 @@ public abstract class CodedOutputStream extends ByteOutput {
} }
private void repositionBuffer(long pos) { private void repositionBuffer(long pos) {
buffer.position(bufferPos(pos)); Java8Compatibility.position(buffer, bufferPos(pos));
} }
private int bufferPos(long pos) { private int bufferPos(long pos) {
@ -2478,7 +2478,7 @@ public abstract class CodedOutputStream extends ByteOutput {
write(value.array(), value.arrayOffset(), value.capacity()); write(value.array(), value.arrayOffset(), value.capacity());
} else { } else {
ByteBuffer duplicated = value.duplicate(); ByteBuffer duplicated = value.duplicate();
duplicated.clear(); Java8Compatibility.clear(duplicated);
write(duplicated); write(duplicated);
} }
} }
@ -2792,7 +2792,7 @@ public abstract class CodedOutputStream extends ByteOutput {
write(value.array(), value.arrayOffset(), value.capacity()); write(value.array(), value.arrayOffset(), value.capacity());
} else { } else {
ByteBuffer duplicated = value.duplicate(); ByteBuffer duplicated = value.duplicate();
duplicated.clear(); Java8Compatibility.clear(duplicated);
write(duplicated); write(duplicated);
} }
} }

@ -313,7 +313,11 @@ public final class Internal {
} }
// ByteBuffer.equals() will only compare the remaining bytes, but we want to // ByteBuffer.equals() will only compare the remaining bytes, but we want to
// compare all the content. // compare all the content.
return a.duplicate().clear().equals(b.duplicate().clear()); ByteBuffer aDuplicate = a.duplicate();
Java8Compatibility.clear(aDuplicate);
ByteBuffer bDuplicate = b.duplicate();
Java8Compatibility.clear(bDuplicate);
return aDuplicate.equals(bDuplicate);
} }
/** Helper method for implementing {@link Message#equals(Object)} for bytes field. */ /** Helper method for implementing {@link Message#equals(Object)} for bytes field. */
@ -353,7 +357,7 @@ public final class Internal {
bytes.capacity() > DEFAULT_BUFFER_SIZE ? DEFAULT_BUFFER_SIZE : bytes.capacity(); bytes.capacity() > DEFAULT_BUFFER_SIZE ? DEFAULT_BUFFER_SIZE : bytes.capacity();
final byte[] buffer = new byte[bufferSize]; final byte[] buffer = new byte[bufferSize];
final ByteBuffer duplicated = bytes.duplicate(); final ByteBuffer duplicated = bytes.duplicate();
duplicated.clear(); Java8Compatibility.clear(duplicated);
int h = bytes.capacity(); int h = bytes.capacity();
while (duplicated.remaining() > 0) { while (duplicated.remaining() > 0) {
final int length = final int length =

@ -140,9 +140,9 @@ class IterableByteBufferInputStream extends InputStream {
updateCurrentByteBufferPos(length); updateCurrentByteBufferPos(length);
} else { } else {
int prevPos = currentByteBuffer.position(); int prevPos = currentByteBuffer.position();
currentByteBuffer.position(currentByteBufferPos); Java8Compatibility.position(currentByteBuffer, currentByteBufferPos);
currentByteBuffer.get(output, offset, length); currentByteBuffer.get(output, offset, length);
currentByteBuffer.position(prevPos); Java8Compatibility.position(currentByteBuffer, prevPos);
updateCurrentByteBufferPos(length); updateCurrentByteBufferPos(length);
} }
return length; return length;

@ -0,0 +1,67 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package com.google.protobuf;
import java.nio.Buffer;
/**
* Wrappers around {@link Buffer} methods that are covariantly overridden in Java 9+. See
* https://github.com/protocolbuffers/protobuf/issues/11393
*
* <p>TODO(b/270454719) remove when Java 8 support is no longer needed.
*/
final class Java8Compatibility {
static void clear(Buffer b) {
b.clear();
}
static void flip(Buffer b) {
b.flip();
}
static void limit(Buffer b, int limit) {
b.limit(limit);
}
static void mark(Buffer b) {
b.mark();
}
static void position(Buffer b, int position) {
b.position(position);
}
static void reset(Buffer b) {
b.reset();
}
private Java8Compatibility() {}
}

@ -5510,6 +5510,12 @@ final class MessageSchema<T> implements Schema<T> {
getMessageFieldSchema(pos).makeImmutable(UNSAFE.getObject(message, offset)); getMessageFieldSchema(pos).makeImmutable(UNSAFE.getObject(message, offset));
} }
break; break;
case 60: // ONEOF_MESSAGE
case 68: // ONEOF_GROUP
if (isOneofPresent(message, numberAt(pos), pos)) {
getMessageFieldSchema(pos).makeImmutable(UNSAFE.getObject(message, offset));
}
break;
case 18: // DOUBLE_LIST: case 18: // DOUBLE_LIST:
case 19: // FLOAT_LIST: case 19: // FLOAT_LIST:
case 20: // INT64_LIST: case 20: // INT64_LIST:

@ -37,7 +37,6 @@ import java.io.InputStream;
import java.io.InvalidObjectException; import java.io.InvalidObjectException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.InvalidMarkException; import java.nio.InvalidMarkException;
@ -110,7 +109,7 @@ final class NioByteString extends ByteString.LeafByteString {
protected void copyToInternal( protected void copyToInternal(
byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
ByteBuffer slice = buffer.slice(); ByteBuffer slice = buffer.slice();
((Buffer) slice).position(sourceOffset); Java8Compatibility.position(slice, sourceOffset);
slice.get(target, targetOffset, numberToCopy); slice.get(target, targetOffset, numberToCopy);
} }
@ -224,7 +223,7 @@ final class NioByteString extends ByteString.LeafByteString {
@Override @Override
public void mark(int readlimit) { public void mark(int readlimit) {
buf.mark(); Java8Compatibility.mark(buf);
} }
@Override @Override
@ -235,7 +234,7 @@ final class NioByteString extends ByteString.LeafByteString {
@Override @Override
public void reset() throws IOException { public void reset() throws IOException {
try { try {
buf.reset(); Java8Compatibility.reset(buf);
} catch (InvalidMarkException e) { } catch (InvalidMarkException e) {
throw new IOException(e); throw new IOException(e);
} }
@ -286,8 +285,8 @@ final class NioByteString extends ByteString.LeafByteString {
} }
ByteBuffer slice = buffer.slice(); ByteBuffer slice = buffer.slice();
((Buffer) slice).position(beginIndex - buffer.position()); Java8Compatibility.position(slice, beginIndex - buffer.position());
((Buffer) slice).limit(endIndex - buffer.position()); Java8Compatibility.limit(slice, endIndex - buffer.position());
return slice; return slice;
} }
} }

@ -1717,7 +1717,7 @@ public final class TextFormat {
if (n == -1) { if (n == -1) {
break; break;
} }
buffer.flip(); Java8Compatibility.flip(buffer);
text.append(buffer, 0, n); text.append(buffer, 0, n);
} }
return text; return text;

@ -770,7 +770,7 @@ final class Utf8 {
if (out.hasArray()) { if (out.hasArray()) {
final int offset = out.arrayOffset(); final int offset = out.arrayOffset();
int endIndex = Utf8.encode(in, out.array(), offset + out.position(), out.remaining()); int endIndex = Utf8.encode(in, out.array(), offset + out.position(), out.remaining());
out.position(endIndex - offset); Java8Compatibility.position(out, endIndex - offset);
} else if (out.isDirect()) { } else if (out.isDirect()) {
encodeUtf8Direct(in, out); encodeUtf8Direct(in, out);
} else { } else {
@ -801,7 +801,7 @@ final class Utf8 {
} }
if (inIx == inLength) { if (inIx == inLength) {
// Successfully encoded the entire string. // Successfully encoded the entire string.
out.position(outIx + inIx); Java8Compatibility.position(out, outIx + inIx);
return; return;
} }
@ -844,7 +844,7 @@ final class Utf8 {
} }
// Successfully encoded the entire string. // Successfully encoded the entire string.
out.position(outIx); Java8Compatibility.position(out, outIx);
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
// TODO(nathanmittler): Consider making the API throw IndexOutOfBoundsException instead. // TODO(nathanmittler): Consider making the API throw IndexOutOfBoundsException instead.
@ -1545,7 +1545,7 @@ final class Utf8 {
} }
if (inIx == inLimit) { if (inIx == inLimit) {
// We're done, it was ASCII encoded. // We're done, it was ASCII encoded.
out.position((int) (outIx - address)); Java8Compatibility.position(out, (int) (outIx - address));
return; return;
} }
@ -1585,7 +1585,7 @@ final class Utf8 {
} }
// All bytes have been encoded. // All bytes have been encoded.
out.position((int) (outIx - address)); Java8Compatibility.position(out, (int) (outIx - address));
} }
/** /**

@ -125,6 +125,7 @@
<include>Internal.java</include> <include>Internal.java</include>
<include>InvalidProtocolBufferException.java</include> <include>InvalidProtocolBufferException.java</include>
<include>IterableByteBufferInputStream.java</include> <include>IterableByteBufferInputStream.java</include>
<include>Java8Compatibility.java</include>
<include>JavaType.java</include> <include>JavaType.java</include>
<include>LazyField.java</include> <include>LazyField.java</include>
<include>LazyFieldLite.java</include> <include>LazyFieldLite.java</include>

@ -189,6 +189,18 @@ public class LiteTest {
} }
} }
@Test
public void testParsedOneofSubMessageIsImmutable() throws InvalidProtocolBufferException {
TestAllTypesLite message =
TestAllTypesLite.parseFrom(
TestAllTypesLite.newBuilder()
.setOneofNestedMessage(NestedMessage.newBuilder().addDd(1234).build())
.build()
.toByteArray());
IntArrayList subList = (IntArrayList) message.getOneofNestedMessage().getDdList();
assertThat(subList.isModifiable()).isFalse();
}
@Test @Test
public void testMemoization() throws Exception { public void testMemoization() throws Exception {
GeneratedMessageLite<?, ?> message = TestUtilLite.getAllLiteExtensionsSet(); GeneratedMessageLite<?, ?> message = TestUtilLite.getAllLiteExtensionsSet();
@ -2349,8 +2361,7 @@ public class LiteTest {
Foo fooWithOnlyValue = Foo.newBuilder().setValue(1).build(); Foo fooWithOnlyValue = Foo.newBuilder().setValue(1).build();
Foo fooWithValueAndExtension = Foo fooWithValueAndExtension =
fooWithOnlyValue fooWithOnlyValue.toBuilder()
.toBuilder()
.setValue(1) .setValue(1)
.setExtension(Bar.fooExt, Bar.newBuilder().setName("name").build()) .setExtension(Bar.fooExt, Bar.newBuilder().setName("name").build())
.build(); .build();
@ -2366,8 +2377,7 @@ public class LiteTest {
Foo fooWithOnlyValue = Foo.newBuilder().setValue(1).build(); Foo fooWithOnlyValue = Foo.newBuilder().setValue(1).build();
Foo fooWithValueAndExtension = Foo fooWithValueAndExtension =
fooWithOnlyValue fooWithOnlyValue.toBuilder()
.toBuilder()
.setValue(1) .setValue(1)
.setExtension(Bar.fooExt, Bar.newBuilder().setName("name").build()) .setExtension(Bar.fooExt, Bar.newBuilder().setName("name").build())
.build(); .build();
@ -2499,9 +2509,9 @@ public class LiteTest {
assertWithMessage("expected exception").fail(); assertWithMessage("expected exception").fail();
} catch (InvalidProtocolBufferException expected) { } catch (InvalidProtocolBufferException expected) {
assertThat( assertThat(
TestAllExtensionsLite.newBuilder() TestAllExtensionsLite.newBuilder()
.setExtension(UnittestLite.optionalInt32ExtensionLite, 123) .setExtension(UnittestLite.optionalInt32ExtensionLite, 123)
.build()) .build())
.isEqualTo(expected.getUnfinishedMessage()); .isEqualTo(expected.getUnfinishedMessage());
} }
} }

@ -47,6 +47,7 @@ message TestAllTypesLite {
message NestedMessage { message NestedMessage {
optional int32 bb = 1; optional int32 bb = 1;
optional int64 cc = 2; optional int64 cc = 2;
repeated int32 dd = 3 [packed = true];
} }
message NestedMessage2 { message NestedMessage2 {

Loading…
Cancel
Save